听说是BestCoder原题.
题目本意是求一个拓扑序,使得1尽量靠前,1靠前的前提下2尽量靠前。。。
我们可以反向思考,建立反图,求字典序最大的拓扑序,然后反向输出即可
(对于一个点,我们将比它大且能放它后面的点都尽量放它后面了,这样理解一下)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<iostream>
#include<algorithm>
#define Eu first
#define Ev second
const int MAXN = 1e5+5, MAXM = 1e5+5;
int n, m;
std::pair<int,int> edge[MAXM];
std::priority_queue<int> heap;
bool ind[MAXN];int rdu[MAXN], cur[MAXN];;
int ans[MAXN], len;
void Init()
{
scanf("%d%d",&n,&m);
for(int i = 1,u,v; i <= m; i++)
{
scanf("%d%d",&u,&v);
edge[i] = std::make_pair(v,u);
}
}
void Build()
{
std::sort(edge + 1,edge + m + 1);
m = std::unique(edge + 1,edge + m + 1) - (edge + 1);
memset(cur,0,sizeof(cur));
for(int i = 1; i <= m; i++) cur[edge[i].Eu]++;
for(int i = 1; i <= n; i++) cur[i] += cur[i-1];
memset(rdu,0,sizeof(rdu));
for(int i = 1; i <= m; i++)
rdu[edge[i].Ev] ++;
for(int i = 1; i <= n; i++)
if(!rdu[i]) heap.push(i);
}
void Solve()
{
len = 0, memset(ind,false,sizeof(ind));
while(!heap.empty())
{
int t = heap.top();
ans[++len] = t, heap.pop();
for(int i = cur[t], p; i > cur[t-1]; i--)
if(!ind[p = edge[i].Ev])
if(!(--rdu[p])) heap.push(p), ind[p] = true;
}
return;
}
void Output()
{
if(len == n)
{
for(int i = n; i >= 1; i--)
printf("%d ",ans[i]);
printf("\n");
}
else
puts("Impossible!");
}
int main()
{
int T;
#ifndef ONLINE_JUDGE
freopen("dishes.in","r",stdin);
freopen("dishes.out","w",stdout);
#endif
scanf("%d",&T);
while(T--)
{
Init();
Build();
Solve();
Output();
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。