2 1 1 2 2 2 1 2 2 1
1777 -1
题意:老板要给n个员工发年终奖金,然后给出m个需求 (a,b),表示a的奖金要比b的多,然后呢,老板决定每个员工至少可以拿888元,现在老板总共至少需要发多少奖金。 如果满足不了就输出-1。
分析:拓扑排序问题。比第i个人奖金少的总人数有sum个,那么第i个人的奖金就是888+sum元。注意此题数据比较大,用邻接表存吧。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2647
代码清单:
(1) vector实现
#include<map> #include<cmath> #include<ctime> #include<queue> #include<stack> #include<cctype> #include<string> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef unsigned int uint; typedef long long ll; typedef unsigned long long ull; const int maxv = 10000 +5; int n,m; int p,q; bool judge; int save[maxv]; int degree[maxv]; vector<int>graph[maxv]; void init(){ memset(degree,0,sizeof(degree)); for(int i=0;i<=n;i++) graph[i].clear(); } int topSort(){ int cnt=0; int sum=0; int q=888; while(cnt<n){ int flag=0; for(int i=1;i<=n;i++){ if(degree[i]==0){ degree[i]=-1; save[flag++]=i; cnt++; } } if(!flag) return -1; sum+=q*flag; q++; for(int i=0;i<flag;i++){ int u=save[i]; for(int j=0;j<graph[u].size();j++){ int v=graph[u][j]; degree[v]--; } } }return sum; } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ init(); for(int i=0;i<m;i++){ scanf("%d%d",&p,&q); judge=false; for(int j=0;j<graph[q].size();j++){ if(graph[q][j]==p){ judge=true; break; } } if(!judge){ graph[q].push_back(p); degree[p]++; } }printf("%d\n",topSort()); }return 0; }
(2)静态邻接表(数组)
#include<map> #include<cmath> #include<ctime> #include<queue> #include<stack> #include<cctype> #include<string> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef unsigned int uint; typedef long long ll; typedef unsigned long long ull; const int maxv = 10000 + 5; const int maxn = 20000 + 5; struct Edge{ int to,next; }graph[maxn]; int n,m; int p,q; int index; bool judge; int save[maxv]; int head[maxn]; int degree[maxv]; void init(){ index=1; memset(head,0,sizeof(head)); memset(degree,0,sizeof(degree)); } void add(int u,int v){ graph[index].to=v; graph[index].next=head[u]; head[u]=index++; } int topSort(){ int cnt=0; int sum=0; int q=888; while(cnt<n){ int flag=0; for(int i=1;i<=n;i++){ if(degree[i]==0){ degree[i]=-1; save[flag++]=i; cnt++; } } if(!flag) return -1; sum+=q*flag; q++; for(int i=0;i<flag;i++){ int u=save[i]; for(int j=head[u];j!=0;j=graph[j].next){ int v=graph[j].to; degree[v]--; } } }return sum; } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ init(); for(int i=0;i<m;i++){ scanf("%d%d",&p,&q); judge=false; for(int j=head[q];j!=0;j=graph[j].next){ if(graph[j].to==p){ judge=true; break; } } if(!judge){ add(q,p); degree[p]++; } }printf("%d\n",topSort()); }return 0; }