您的位置:首页 > 其它

POJ 3687 Labeling Balls

2017-03-31 17:06 302 查看
http://poj.org/problem?id=3687

题意:

有n个小球,权重分别为1~n。现在要为这些小球贴上1~n的标签,规则是标签1所对应的小球的权重应尽量小,其次是标签2...接下来会有m个要求,就是标签a所贴小球的权重必须小于标签b所贴小球的权重。

思路:

拓扑排序。

首先我考虑的是正向的拓扑排序,建好图后每次选择度数为0的最小的顶点,为它贴上当前权重最小的小球。但是这样做有缺陷,举个例子来说:

53
14
42
35
正确答案应该是输出13425,但是如果按照我的做法去做的话,输出的是14235。因为2在4后面,先处理了3,这样导致了标签2所贴球的权重较大,最优的是先处理4,这样2就能有较小值。
于是考虑用反向拓扑来做,每次将小的那端的度数+1,每次选择度数为0的最大的顶点,为它贴上当前权重最大的小球。这样就保证了大标签贴在了权重大的球上。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
usingnamespacestd;

constintmaxn=200+5;

intn,m;
intg[maxn][maxn];
intindegree[maxn];
intans[maxn];

inttuopu()
{
intcnt=n;
for(inti=1;i<=n;i++)
{
intnum=0,loc;
for(intj=1;j<=n;j++)
{
if(indegree[j]==0)
{
num++;
loc=j;
}
}
if(num==0)return-1;
ans[loc]=cnt--;
indegree[loc]=-1;
for(intj=1;j<=n;j++)
if(g[loc][j])indegree[j]--;
}
return1;
}

intmain()
{
//freopen("D:\\txt.txt","r",stdin);
intT;
intx,y;
scanf("%d",&T);
while(T--)
{
memset(g,0,sizeof(g));
memset(indegree,0,sizeof(indegree));
memset(ans,0,sizeof(ans));
boolflag=true;
scanf("%d%d",&n,&m);
while(m--)
{
scanf("%d%d",&x,&y);
if(x==y)flag=false;
//反向拓扑
if(!g[y][x])//这里需要注意一下重边的问题
{
g[y][x]=1;
indegree[x]++;
}
}
if(flag)
{
intp=tuopu();
if(p==-1)printf("-1\n");
else
{
for(inti=1;i<n;i++)
cout<<ans[i]<<"";
cout<<ans
<<endl;
}
}
elseprintf("-1\n");
}
return0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: