题目连接:http://acm.pku.edu.cn/JudgeOnline/problem?id=3687
题目大意:给n个点,其中有些点之间是有轻重关系的,如给定两个点a,b,那么 a的重量必定要小余b,题目求的是一个序列,要求是标号的小的点重量小的点尽可能的排在前面。。。要是其中成环了 则无解。。。。。。
起初我就是按照普通的拓扑排序算法加上限制条件写了,但是一直wa!后来看了别人的解题报告才明白,既然不能保证编号小重量小的点一定排在前面,那么有一点事可以肯定的,那就是编号大的重量大的一定排在后面,那么我们就从后面开始排,一直到最前面。那么在同一队列q中的点可视为是重量相同的,我们只要从里面选出编号大的点相对而言排在最后就可以了。。。
如果排到最后面,点的个数<n 那么其中必定有环 则无解!
代码:
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int MAX=205; int map[MAX][MAX]; int out[MAX]; int tp[MAX]; int q[60000]; int visit[MAX]; int n,m,cnt; bool Topsort() { for(int i=n;i>=1;i--) if(out[i]==0) { q[cnt++]=i; visit[i]=1; } int u,v,j=n; for(int k=1;k<=n;k++) { u=0; for(int i=0;i<cnt;i++) if(q[i]>u) { u=q[i]; v=i; } if(u>0) { tp[j--]=u; q[v]=-1; } for(int i=1;i<=n;i++) { if(map[i][u]&&!visit[i]) { out[i]--; if(out[i]==0) { q[cnt++]=i; visit[i]=1; } } } } if(j>0) return false; return true; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); cnt=0; memset(map,0,sizeof(map)); memset(out,0,sizeof(out)); memset(visit,0,sizeof(visit)); int s,e; for(int i=0;i<m;i++) { scanf("%d%d",&s,&e); if(map[s][e]==0) out[s]++; map[s][e]=1; } bool more=Topsort(); if(!more) printf("-1/n"); else { for(int i=1;i<=n;i++) visit[tp[i]]=i; printf("%d",visit[1]); for(int i=2;i<=n;i++) printf(" %d",visit[i]); printf("/n"); } } return 0; }