1. 程式人生 > >Codeforces Round #541 (Div. 2) D 並查集 + 拓撲排序

Codeforces Round #541 (Div. 2) D 並查集 + 拓撲排序

相等 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 並查集 + 拓撲排序