P3243 [HNOI2015]菜肴制作(拓扑+优先队列+贪心)
思路
一开始会很显然的想到要用拓扑排序,想着不就是要找字典序最小的拓扑序列嘛,那也太水了,于是,发现有问题,正着的时候 我得知道他的叶子节点的最小值,然后跑当前根节点到叶子结点最小值的绝对路径,但是这样不好搞。
于是乎,想到建立反图,从最小值开始跑,那么从最小值跑到叶子节点的路径就是答案,然后其实对于每一层还是要跑拓扑,因为是反一反 所以就丢一个优先队列,跑值最大的点就行,然后最后reverse一下。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
//#pragma GCC optimize(3)
#define pb push_back
#define is insert
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define show(x) cerr<<#x<<" : "<<x<<endl;
//mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
//ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
const int INF=0x3f3f3f3f;//2147483647;
const int N=1e5+50,M=1e4+50;
const ll mod=1e9+7;
int n,m;
vector<int>to[N];
vector<int>ans;
int in[N];
priority_queue<int>q;
void solve() {
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v;cin>>u>>v;
to[v].pb(u);
in[u]++;
}
int cnt=0;
for(int i=1;i<=n;i++){
if(in[i]==0){
q.push(i);
}
}
while(!q.empty()){
int u=q.top();cnt++;q.pop();
ans.pb(u);
for(auto i:to[u]){
in[i]--;
if(!in[i]){
q.push(i);
}
}
}
if(cnt!=n){
cout<<"Impossible!"<<"\n";
}
else {
reverse(ans.begin(),ans.end());
for(auto i:ans){
cout<<i<<" ";
}cout<<"\n";
}
ans.clear();
for(int i=1;i<=n;i++){
to[i].clear();
in[i]=0;
}
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int __=1;cin>>__;
while(__--){
solve();
}
return 0;
}

浙公网安备 33010602011771号