HDU2647 Reward(拓扑排序+链式前向星)

Reward

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7819    Accepted Submission(s): 2488


Problem Description
Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now he has a trouble about how to distribute the rewards.
The workers will compare their rewards ,and some one may have demands of the distributing of rewards ,just like a's reward should more than b's.Dandelion's unclue wants to fulfill all the demands, of course ,he wants to use the least money.Every work's reward will be at least 888 , because it's a lucky number.


Input
One line with two integers n and m ,stands for the number of works and the number of demands .(n<=10000,m<=20000)
then m lines ,each line contains two integers a and b ,stands for a's reward should be more than b's.


Output
For every case ,print the least money dandelion 's uncle needs to distribute .If it's impossible to fulfill all the works' demands ,print -1.


Sample Input
2 1
1 2
2 2
1 2
2 1


Sample Output
1777
-1


Author
dandelion
这道题的题意就是:一个boss给员工发红包,最少是888,并且要求花费最少的钱数。
样例的意思是:
2 1
1 2
两个员工,12的钱多,所以输出是(888+889=1777)(889可以理解吧)
2 2
1 2
2 1
这里12多,2还比1多,明显不成立。
这里我们可以建一个有向图(这里需要反向建图),然后拓扑排序,按照拓扑序输出最终的钱数,如果出现环则输出-1.
建图,例如,
1 3
1 2
那么,1的入度为2,3,2的入度为0,拓扑序就是2->3->1(或者3->2->1),就这样子,这里用到链式前向星,大神说很好用,就学了。
然后就O了。

[链式前向星相关]

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define MOD 1000000007
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define Pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define Pi 4.0*atan(1.0)

#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-12;
const int maxn = 20010;
using namespace std;

inline int read(){
    int x(0),f(1);
    char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
struct edge{
    int to;
    int next;
};
edge G[maxn];
int tot,head[maxn],deg[maxn],money[maxn];
void init()
{
    mes(head,-1);
    mes(deg,0);
    tot=0;
}
inline void addEdge(int u,int v)
{
    G[tot].to=v;
    G[tot].next=head[u];
    head[u]=tot++;
}
void topoSort(int n)
{
    int re=0;
    int ed=0;
    queue<int> que;
    for(int i=1;i<=n;++i){
        if(0==deg[i]){ //先把入度为0的点压入栈中
            que.push(i);
        }
    }
    while(!que.empty()){
        int u=que.front(); 
        que.pop();
        re+=money[u]; 
        ++ed; //记录点的个数,最后判断是否有解
        for(int i=head[u];~i;i=G[i].next){ ///枚举与队首元素u有关的边 
            if(--deg[G[i].to]==0){
                que.push(G[i].to);
                money[G[i].to]=money[u]+1; //下一个点所代表的人钱比前一个点多一
            }
        }
    }
    if(ed!=n){ //拓扑序的长度刚好等于工人的数量则有解
        puts("-1");
    }
    else{
        printf("%d\n",re);
    }
}
int main()
{
    //fin;
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        int u,v;
        init();
        for(int i=1;i<=n;++i){
            money[i]=888;
        }
        while(m--){
            u=read(),v=read();
            addEdge(v,u); //反向建图
            ++deg[u];
        }
        topoSort(n);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值