E. Directing Edges 解析(思維、拓樸排序)
阿新 • • 發佈:2020-12-08
Codeforce 1385 E. Directing Edges 解析(思維、拓樸排序)
今天我們來看看CF1385E
題目連結
題目
給一張圖,其中有些邊一開始就是有向邊,有些邊一開始沒給定方向。求是否可能有一種邊的方向指定,能夠讓整張圖變成有向無環圖。
前言
完全不會......
觀看更多正版原始文章請至petjelinux的blog
想法
首先先只把固定好方向的邊放到圖上,並且跑一遍拓樸排序,我是使用每次處理入度為零的點的方法,並且用queue處理下一個要看的點的方法。
注意到,這個方法處理的點的順序是(如果處理的圖是有向無環圖),會是深度為0的點先被處理完,然後才會是深度為1的點。。。
如此一來,我們紀錄每個點被處理的順序。如果發現最後總編號小於\(n\)
那麼接下來我們考慮未定向的邊,觀察到,只要將邊從編號小的點連到編號大的,就一定不會有環,因為我們上面說過,編號小的深度也小。
程式碼:
const int _n=2e5+10; int t,n,m,_,cnt,num[_n],in[_n],x,y; bool vis[_n]; queue<int> q; vector<PII> es,ans; VI G[_n]; main(void) {ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); cin>>t;while(t--){ cin>>n>>m;rep(i,0,n+1)G[i].clear();es.clear(),ans.clear();while(!q.empty())q.pop(); memset(num,0,sizeof(num[0])*(n+1)),cnt=0,memset(in,0,sizeof(in[0])*(n+1)); rep(i,0,m){cin>>_>>x>>y;if(!_)es.pb({x,y});else G[x].pb(y),in[y]++,ans.pb({x,y});} rep(i,1,n+1)if(!in[i])q.push(i); while(!q.empty()){ int now=q.front();q.pop(); num[now]=cnt++;vis[now]=1;for(int u:G[now]){in[u]--;if(!in[u])q.push(u);} }if(cnt<n){cout<<"NO\n";goto A;} cout<<"YES\n"; for(PII e:es)if(num[e.fi]<num[e.se])cout<<e.fi<<' '<<e.se<<'\n'; else cout<<e.se<<' '<<e.fi<<'\n'; for(PII e:ans)cout<<e.fi<<' '<<e.se<<'\n'; A:; } return 0; }
標頭、模板請點Submission看
Submission