题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2647
题面:
2 1 1 2 2 2 1 2 2 1
1777 -1
#include <iostream> #include <cstdio> #include <cstring> #include <set> #include <queue> using namespace std; //s集合排重边,据说没有 set <int> s; //分别为权值,入度,邻接表的头位置,cnt邻接表的计数值 int val[10010],in[10010],head[10010],cnt=0; //访问标记 bool vis[10010]; //边存储 struct edge { int to,next; }ee[20010]; //加边操作 void add_edge(int a,int b) { ee[cnt].to=b; //接上后续地址 ee[cnt].next=head[a]; head[a]=cnt++; } queue <int> qe; int max(int a,int b) { return a>b?a:b; } int main() { int n,m,a,b,tmp,ans,cur,v,to; bool flag; while(~scanf("%d%d",&n,&m)) { flag=true; cnt=0; ans=0; while(!qe.empty()) qe.pop(); s.clear(); //赋初值 for(int i=1;i<=n;i++) val[i]=888; //初始化 memset(in,0,sizeof(in)); memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); for(int i=0;i<m;i++) { //这写反了,wa了一次 scanf("%d%d",&b,&a); tmp=a*10000+b; //排重 if(!s.count(tmp)) { //加边,统计入度,最小的点,入度为0 add_edge(a,b); in[b]++; } } for(int i=1;i<=n;i++) { if(in[i]==0) { qe.push(i); ans+=888; vis[i]=1; } } while(!qe.empty()) { cur=qe.front(); qe.pop(); v=val[cur]+1; for(int i=head[cur];i!=-1;i=ee[i].next) { to=ee[i].to; //取最大值,以确保满足 val[to]=max(val[to],v); //不断加入入度为0的点 in[to]--; if(in[to]==0) { ans+=val[to]; vis[to]=1; qe.push(to); } } } //如果还有没访问过的点,就是存在矛盾 for(int i=1;i<=n;i++) { if(!vis[i]) { flag=false; break; } } if(flag) printf("%d\n",ans); else printf("-1\n"); } return 0; }