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

Posted virtu0s0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #541 (Div. 2) D 并查集 + 拓扑排序相关的知识,希望对你有一定的参考价值。

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 并查集 + 拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #541 题解

Codeforces Round #541 (Div. 2) (A~F)

codeforces Round #541 (Div 2)

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

Codeforces Round #541 (Div. 2) E 字符串 + 思维 + 猜性质

cf-Round541-Div2-F(并查集+静态链表)