hdu2647 Reward

题目链接:点击打开链接

题意描述:在一个公司中,老板打算给员工发奖励,每个员工至少发888,但是员工之间奖励需要满足一些条件,如 a b代表a的奖励要比b至少多1,现在给定n个员工,和m的条件,问老板能否满足员工的要求(可能存在a比b多,同时b又比a多,此时无法满足),如果能够满足,老板至少需要准备多少?


解题思路:

1、我们可以根据条件建图,如果a比b多,则建一条b->a的有向边

2、判断有向图中是否存在回路,如果存在回路则无法满足要求(注意:图不保证是联通的,可能存在好多个联通块)

3、如果满足要求,我们可以把入度为0的点加入队列中,然后更新其他点

代码:

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <queue>
#define MAXN 10010
#define MAXE 20010
#define INF 0x7fffffff
using namespace std;
int head[MAXN];
struct Edge{
    int to,_next;
}edge[MAXE*2];
int tol;
void init(){
    tol=0; memset(head,-1,sizeof(head));
}
void addEdge(int from,int to){
    edge[tol].to=to;edge[tol]._next=head[from];head[from]=tol++;
}
int n,m;
int inn[MAXN],dis[MAXN];
bool vis[MAXN];
bool dfs(int s){
    for(int i=head[s];i!=-1;i=edge[i]._next){
        int to=edge[i].to;
        if(vis[to]) return true;
        else{
            vis[to]=true;
            if(dfs(to)) return true;
            vis[to]=false;
        }
    }
    return false;
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0) {printf("0\n");continue;}
        init();
        memset(inn,0,sizeof(inn));
        int from,to;
        bool flag=false;
        for(int i=1;i<=m;++i){
            scanf("%d%d",&to,&from);
            if(from==to) flag=true;
            addEdge(from,to);
            inn[to]++;
        }
        if(flag) {printf("-1\n");continue;}
        for(int i=1;i<=n;++i) dis[i]=0;
        queue<int> q; while(!q.empty()) q.pop();
        int i;
        //flag=false;
        for(i=1;i<=n;++i){
           // if(inn[i]) continue;///注意,忽悠了连个联通块的情况,如一个孤立点和一个环的情况 
            //else flag=true;            
            memset(vis,false,sizeof(vis));
            vis[i]=true;
            if(dfs(i)) break;
            dis[i]=0;
            q.push(i);
        }
        if(i<=n){ printf("-1\n");continue; }
        while(!q.empty()){
            int t=q.front(); q.pop();
            for(int i=head[t];i!=-1;i=edge[i]._next){
                int to=edge[i].to;
                if(dis[to]<dis[t]+1){
                    dis[to]=dis[t]+1;
                    q.push(to);
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n;++i)
            ans+=dis[i];
        printf("%d\n",ans+n*888);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值