HDU-2647拓扑排序
这道题不能用矩阵表示,因为1w*1w绝对超内存,分析数据,前一个a的钱要多于后一个b,所以我们要把b作为出度,a为入度,如果不明白这个地方,举例:b——>a——>c——>d ,b为888,钱数逐渐上升,如果反过来a为出度就不符合题意啦。。。
还有一个地方需要注意:判断输出-1的情况不能只判断没有一个入度为0的点,因为有可能在中间就出现矛盾了,如:a——>b——>c——>d——>c 有入度为0的点,但却要输出-1;
#include<iostream> #include<cstring> #include<queue> #include<cstdio> using namespace std; #define MAX 10005 int n,sum,ans; int into[MAX],head[MAX],money[MAX]; struct Reward { int to; int next; } edge[2*MAX]; void topu() { int i,j,l,v; queue<int>Q; for(i=1; i<=n; i++) if(into[i]==0) Q.push(i);//把入度为0的点压如队列 while(!Q.empty()) { v=Q.front();//调用首位元素 sum+=money[v]; Q.pop();//出队 ans++; //用一个变量记录调用元素的总量,最后与n作比较 for(l=head[v]; l!=-1; l=edge[l].next)//与队首元素v有关的都枚举一遍 { if(--into[edge[l].to]==0)//如果入度-1为0,即为v的下一个元素 { Q.push(edge[l].to);//将其压入队列 money[edge[l].to]=money[v]+1;//保证后一个要比前一个多1 } } } } int main() { int m,a,b,tot; while(scanf("%d%d",&n,&m)!=EOF) { memset(head,-1,sizeof(head)); memset(into,0,sizeof(into)); for(int i=1; i<=n; i++) money[i]=888;//所有人一开始都为888 tot=0; sum=0; ans=0; while(m--) { scanf("%d%d",&a,&b);//注意要逆过来,因为后一个b是基础的888,应当作为出度 edge[tot].to=a; edge[tot].next=head[b]; head[b]=tot++; into[a]++;//记录入度 } topu(); if(ans!=n)//有可能在中间出现矛盾,必须保证每个地方都不矛盾 sum=-1; cout<<sum<<endl; } }