题意:问字典序最小的拓扑序
解:反向拓扑
正向不行的有一个很简单的样例就是
5 1
5 1
反向可行:
我们每次都给出度==0的index最大点赋大值,为什么这样是对的。
考虑在多个出度==0的点之间选不是最大的赋值,那么一定不合理。首先想到不是最大那个(作为较小点被选择)一定亏了,他本来可以更小的。那么虽然他自己亏了,那么就剩一种情况了会不会有index小的点因为先选较小的点而值更小呢?
不会的,
对更小点进行赋值时在现在的情况下,他本身不亏应该是被作为一个最大点的(若作为较小点来选择,它自己一定不合适)
所以我们上一步选一个较小点是为了比(较小)点index小的点的更优,那么后来index小的点一定是在作为一个最大点进行决策的。
很显然作为最大点被选择的点不会因为反向决策过程中前面选择较小点,自身作为决策中的最大点出现的更晚。
(解释一下:因为在选较小点那步不是有最大点没选嘛,较小点被选择且作为最大点,那么之前那步最大点的效果还是释放了)
所以(最大,最大,。。。。,最大,最大)优于其它的策略
所以每次都找出度==0的index最大点。
#include<bits/stdc++.h>
#define en '\n'
#define ll long long
const int maxn =2e5+10;
using namespace std;
int rd(){int t;scanf("%d",&t);return t;}
vector<int>vec[maxn];
int du[maxn],ans[maxn];
priority_queue<int,vector<int>,less<int> >q;
signed main()
{
#ifdef local
freopen("input2.txt","r",stdin);
#endif
int n,m;
cin>>n>>m;
#define pb push_back
for(int i=1;i<=m;i++){
int x,y;
x=rd(),y=rd();
vec[y].push_back(x);
du[x]+=1;
}
for(int i=1;i<=n;i++){
if(!du[i]){
q.push(i);
}
}
int ind=n+1;
while(q.size()){
int x=q.top();q.pop();
ans[x]=--ind;
for(int i=0;i<vec[x].size();i++){
int y=vec[x][i];
du[y]-=1;
if(!du[y])q.push(y);
}
}
for(int i=1;i<=n;i++)cout<<ans[i]<<' ';
return 0;
}