[HDU] 2647 Reward(拓扑排序)
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2647
拓扑排序问题,反向建图,则最后入度为0的点初始金钱为888,以后每次删边入度为0的点金钱比上次+1即可。若存在环,则不可能出现,输出-1。
1 #include<cstdio> 2 #include<iostream> 3 #include<string.h> 4 #include<algorithm> 5 #include<math.h> 6 #include<stdbool.h> 7 #include<time.h> 8 #include<stdlib.h> 9 #include<set> 10 #include<map> 11 #include<stack> 12 #include<queue> 13 #include<vector> 14 using namespace std; 15 #define clr(x,y) memset(x,y,sizeof(x)) 16 #define sqr(x) ((x)*(x)) 17 #define rep(i,a,b) for(int i=(a);i<=(b);i++) 18 #define LL long long 19 #define INF 0x3f3f3f3f 20 #define A first 21 #define B second 22 const int N=10000+131; 23 const int M=888; 24 int n,m,cnt,sum,num,d[N],head[N],path[N]; 25 26 struct node 27 { 28 int u,v; 29 int next; 30 } edge[2*N]; 31 32 void init() 33 { 34 clr(d,0); 35 clr(head,-1); 36 cnt=0; 37 sum=0; 38 num=-1; 39 } 40 41 void add(int u,int v) 42 { 43 edge[cnt].v=v; 44 edge[cnt].next=head[u]; 45 head[u]=cnt++; 46 } 47 48 void solve() 49 { 50 int u,i,f,p,x,y,res; 51 while(~scanf("%d%d",&n,&m)) { 52 init(); 53 while(m--) { 54 scanf("%d%d",&x,&y); 55 add(y,x); 56 d[x]++; 57 } 58 59 for(int i=0;i<n;i++) { 60 num++; 61 f=0;p=0;res=0; 62 for(int j=1;j<=n;j++) { 63 if(!d[j]) { 64 u=j; 65 d[j]--; 66 sum+=M+num; 67 f=1; 68 path[res++]=j; 69 } 70 if(d[j]>0) p=1; 71 } 72 73 if(!f && p){ //有入度大于0的点,但不存在入度为0的点。即存在环 74 sum=-1; 75 break; 76 } 77 78 for(int k=0;k<res;k++) { 79 u=path[k]; 80 for(int j=head[u];j!=-1;j=edge[j].next) { 81 d[edge[j].v]--; 82 } 83 } 84 } 85 printf("%d\n",sum); 86 } 87 } 88 int main() 89 { 90 solve(); 91 return 0; 92 }