给出一些球,从1~N编号,他们的重量都不相同,也用1~N标记加以区分(这里真心恶毒啊,估计很多WA都是因为这里),然后给出一些约束条件,< a , b >要求编号为 a 的球必须比 b 轻,现在要求按编号升序输出每个球的重量,如果有多种解,输出字典序最小的那个。
例如:
input:
1
5 4
5 1
4 2
1 3
2 3
output:
2 4 5 3 1
输出的意思是,编号为 1 的球的重量是 2,编号为 2 的球重量为 5,编号 3 的球重量为 5,编号 4 的球重量为 3,编号 5 的球重量为 1 。
显然的这满足了 input 的所有约束条件,而且字典序最小。
开始直接拓扑整的,WA掉了,看discuss里面各大牛X提示,才发现我这样的不到要求的序列……
需要注意的:
node1:反向建图
node2:考虑重边
ps:感谢
http://imlazy.ycool.com/post.2144071.html
http://www.answeror.com/archives/23913
两组给力数据:http://poj.org/showmessage?message_id=145313
我的代码:
#include<algorithm> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N = 210; struct point{ int id,de;//入度 bool operator < (const point &a) const{ return a.id > id; } }; point p[N]; int n,m,map[N][N],vis[N]; void getmap() { int i,a,b; for(i=1;i<=n;p[i].id=i,p[i++].de=0); memset(map,0,sizeof(map)); while(m--){ scanf("%d%d",&a,&b); if(map[b][a]==0){ map[b][a]=1;p[a].de++; } } } void solve() { point cur; priority_queue <point> q; int i,j,k=1,ans[N],a[N]; memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++){//所有入度为0的点先入队 if(p[i].de==0)q.push(p[i]); } int tol=0; while(!q.empty()){ cur=q.top(); q.pop(); if(cur.de==0 && !vis[cur.id]){ a[k++]=cur.id; vis[cur.id]=1; tol++; for(j=1;j<=n;j++){ if(!vis[ p[j].id ]){ if(map[cur.id][p[j].id])p[j].de--; if(p[j].de==0)q.push(p[j]); } } } } if(tol<n)printf("-1"); else { for(i=1;i<k;i++) ans[ a[k-i] ] = i; printf("%d",ans[1]); for(i=2;i<=n;i++) printf(" %d",ans[i]); } puts(""); } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); getmap(); solve(); } return 0; }