[CF1131D] Gourmet choice - 拓扑排序,并查集

时间:2020-03-26
本文章向大家介绍[CF1131D] Gourmet choice - 拓扑排序,并查集,主要包括[CF1131D] Gourmet choice - 拓扑排序,并查集使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

有两个正整数序列 \(a,b\),长度分别为 \(n,m\)。给出所有 \(a_i\)\(b_j\) \((1\le i\le n,1\le j\le m)\) 的大小关系(大于,小于或者等于),请构造出符合条件的 \(a\)\(b\)。如果无解,输出 NO。如果有多个解,输出 \(a,b\) 中最大元素最小的方案。

Solution

并查集将所有等于的数合并起来,然后建图拓扑排序,最后 check 一下拓扑排序的结果以检查是否有环

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 2005;

int n,m,g[N][N],fa[N],a[N],b[N];
char c[N][N];

int find(int p) {
    return fa[p]==p ? p : fa[p]=find(fa[p]);
}

void merge(int p,int q) {
    p=find(p); q=find(q);
    if(p!=q) fa[p]=q;
}

void dfs(int p) {
    b[p]=1;
    for(int i=1;i<=n+m;i++) {
        if(g[p][i]) {
            if(b[i]) {
                cout<<"No";
                exit(0);
            }
            if(a[i]==0) dfs(i);
            a[p]=max(a[p],a[i]);
        }
    }
    b[p]=0;
    ++a[p];
}

signed main() {
    cin>>n>>m;
    for(int i=1;i<=n+m;i++) fa[i]=i;
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            cin>>c[i][j];
            if(c[i][j]=='=') {
                merge(i,n+j);
            }
        }
    }
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            if(c[i][j]=='<') {
                g[find(j+n)][find(i)]=1;
            }
            if(c[i][j]=='>') {
                g[find(i)][find(j+n)]=1;
            }
        }
    }
    for(int i=1;i<=n+m;i++) if(a[i]==0) dfs(i);
    cout<<"Yes"<<endl;
    for(int i=1;i<=n;i++) cout<<a[find(i)]<<" ";
    cout<<endl;
    for(int i=1;i<=m;i++) cout<<a[find(i+n)]<<" ";
    cout<<endl;
}

$flag 上一页 下一页