之所以把这个题放到贪心里,是因为拓扑排序都会写,中间的贪心才是关键。
题意是给出几组数据,给出了球下标之间的大小关系~
把1—n的重量分配给这n个小球~
让从输出标号1—n的球的重量~
反正样例给的挺坑爹~要仔细读题啊~
正常拓扑排序,得到的是球的下标最小的顺序,但进而得到的按
下标排序的重量的排序不一定是最小的,正常的拓扑排序是优先
选择入度为零且标号小的点如队列,而反向拓扑(且优先选择下
标大的点如队列)则是让大的点尽量靠后,区别是什么呢?
如下例子:n=5
1 4
4 2
3 5
下标对应的重量:1 2 3 4 5
正向排序 下标:1 3 4 2 5
重量:1 4 2 3 5
逆向排序 下标:1 4 2 3 5
重量:1 3 4 2 5
正确的排序思想:在下标排序中,尽量让大的点靠后,这样在重
量排序中,重量小的才会尽量向前(仔细)看
上述例子;
#include <iostream>
#include <queue>
using namespace std;
int n,m;
struct node
{
int v,next;
}edge[40001];
int pre[201];
int inn[201];
int low[201];
bool used[201];
bool tupo()
{
int sum=n;
int out;
priority_queue<int> l;
for(int i=1;i<=n;i++)
if(inn[i]==0)
l.push(i);
while(!l.empty())
{
out=l.top();
l.pop();
used[out]=true;
low[out]=sum--;
for(int i=pre[out];i!=-1;i=edge[i].next)
{
if(!used[edge[i].v]&&(--inn[edge[i].v])==0)
l.push(edge[i].v);
}
}
if(sum!=0)
return false;
return true;
}
int main()
{
int c;
cin>>c;
while(c--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
pre[i]=-1;
inn[i]=0;
used[i]=false;
}
int x,y;
for(int i=1;i<=m;i++)
{
bool t=true;
cin>>y>>x;
for(int j=pre[x];j!=-1;j=edge[j].next)
if(edge[j].v==y)
{
t=false;
break;
}
if(t)
{
inn[y]++;
edge[i].v=y;
edge[i].next=pre[x];
pre[x]=i;
}
}
if(tupo())
{
for(int i=1;i<=n;i++)
{
cout<<low[i];
if(i!=n)
cout<<" ";
}
cout<<endl;
}
else
cout<<"-1"<<endl;
}
return 0;
}