给出一些球,从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;
}