题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2647
去了趟厕所回来立马来灵感了啊。。第一次的时候纠结拓扑的顺序,加钱的时候顺序正好反着,在厕所的时候突然想到可以在加边的时候就倒着加,这样不就正好了吗。。于是回来怒敲代码,然后1Y,爽啊。。于是就多写点注释吧。。
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map> #include <algorithm> using namespace std; int d[11000], head[11000], n, cnt, a[11000]; struct node { int u, v, w; int next; }edge[22000]; void add(int u, int v, int w) { edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void tops() { int i, j, x, ss=888, ans=0, s=0, flag=0;//ss表示当前层数要加的钱数;ans表示总钱数;s表示当前选的总人数 while(1) { x=0; for(j=1;j<=n;j++) { if(d[j]==0) { a[x++]=j;//记录此层选的人 d[j]--; s++; } } ans+=x*ss; if(x==0&&s<n) { flag=1;//说明出现环,则不能满足要求 break; } if(x==0) break; for(i=0;i<x;i++)//将与该层所有人相连的均降度 { for(j=head[a[i]];j!=-1;j=edge[j].next) { if(edge[j].w==1) { edge[j].w--; d[edge[j].v]--; } } } ss++;//层数递增 } if(flag) printf("-1\n"); else printf("%d\n",ans); } int main() { int m, a, b; while(scanf("%d%d",&n,&m)!=EOF) { memset(d,0,sizeof(d)); memset(head,-1,sizeof(head)); cnt=0; while(m--) { scanf("%d%d",&a,&b); add(b,a,1); d[a]++; } tops(); } return 0; }