Codeforces Round #541 (Div. 2) D 並查集 + 拓撲排序
阿新 • • 發佈:2019-03-11
相等 scanf end href 關系 top 二維 || back
https://codeforces.com/contest/1131/problem/D
題意
給你一個n*m二維偏序表,代表x[i]和y[j]的大小關系,根據表構造大小分別為n,m的x[],y[],使得兩個數組中最大的數盡量小
題解
- 按照偏序表,構造出從小到大的拓撲圖
- 如何解決相等的數的偏序關系?
- 用並查集縮點後再進行拓撲排序
- 如何解決最大的數最小?
- 只需要使得同一層的數相同就行,可以一批處理棧中的元素,對於一批棧中的元素產生的新點,先放進一個容器裏,然後等到這批棧清空了,再把這個容器中的點放進棧中
坑點
- 需要標記已經進棧的並查集,防止同一個並查集重復進棧
代碼
#include<bits/stdc++.h> #define M 4005 using namespace std; int n,m,i,j,in[M],u,v,c[M],cnt; char s[M][M]; stack<int>S; queue<int>Q; vector<int>g[M]; int fa[M];int fin(int u){return fa[u]==u?u:fa[u]=fin(fa[u]);} void merge(int u,int v){ int x=fin(u),y=fin(v); if(x!=y)fa[x]=y; } int main(){ cin>>n>>m; for(i=1;i<=n+m;i++)fa[i]=i; for(i=1;i<=n;i++)scanf("%s",s[i]+1); for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ if(s[i][j]=='='){ merge(i,j+n); } } } for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ u=fin(i);v=fin(j+n); if(s[i][j]=='>'){ in[u]++;g[v].push_back(u); }else if(s[i][j]=='<'){ in[v]++;g[u].push_back(v); } } } cnt++; for(i=1;i<=n+m;i++){ u=fin(i); if(in[u]==0&&!c[u]){ S.push(u); c[u]=cnt; } } while(!S.empty()||!Q.empty()){ if(!S.empty()){ u=S.top();S.pop(); for(i=0;i<g[u].size();i++){ v=g[u][i];in[v]--; if(in[v]==0){ Q.push(v); } } }else{ cnt++; while(!Q.empty()){ u=Q.front();Q.pop(); c[u]=cnt;S.push(u); //cout<<u<<" "<<c[u]<<endl; } } } for(i=1;i<=n+m;i++){ u=fin(i); if(in[u]>0){cout<<"No";return 0;} } cout<<"Yes"<<endl; for(i=1;i<=n+m;i++){ u=fin(i); cout<<c[u]<<" "; if(i==n)cout<<endl; } }
Codeforces Round #541 (Div. 2) D 並查集 + 拓撲排序