思路:拓扑排序,注意根据题的要求,要先保证1号球最轻,如果我们由轻的向重的连边,然后我们依次有小到大每次把重量分给一个入度为0的点,那么在拓扑时我们面对多个入度为0的点,我们不知道该把最轻的分给谁才能以最快的速度找到1号(使1号入度为0),并把当前最轻的分给1号。所以我们要由重的向轻的连边,然后从大到小每次把一个重量分给一个入度为0的点。这样我们就不用急于探求最小号。我们只需要一直给最大号附最大值,尽量不给小号赋值,这样自然而然就会把轻的重量留给小号。题目中可能有重边,用邻接矩阵存储必须注意,但是用邻接表存储恰恰避免了处理邻边的问题(http://www.cnblogs.com/rainydays/archive/2011/07/20/2112047.html)
#include <stdio.h> #include <string.h> #define N 205 #define M 40005 struct edge{ int y,next; }e[M]; int n,m,T,top; int d[N],first[N],res[N]; void add(int x,int y){ e[top].y = y; e[top].next = first[x]; first[x] = top++; } void topsort(){ int i,j,k; for(i = n;i>=1;i--){ for(j = n;j>=1;j--) if(!d[j]){ d[j]--; break; } if(!j){ printf("-1\n"); return; } res[j] = i; for(k = first[j];k!=-1;k=e[k].next)//如果有重边也一次全部消除掉了 d[e[k].y]--; } for(i = 1;i<=n;i++) printf("%d ",res[i]); putchar('\n'); } int main(){ freopen("a.txt","r",stdin); scanf("%d",&T); while(T--){ int i,a,b; memset(first,-1,sizeof(first)); top = 0; memset(d,0,sizeof(d)); scanf("%d %d",&n,&m); for(i = 0;i<m;i++){ scanf("%d %d",&a,&b); add(b,a); d[a]++; } topsort(); } return 0; }