拓扑排序+并查集——cf1131D

以前做过了忘记掉了。。拓扑排序如果要处理等于关系,就要用并查集把相等关系进行缩点

/*
1.相等关系用并查集合并
2.不等关系用有向边链接
3.拓扑排序求顺序 
*/
#include<bits/stdc++.h>
#include<vector>
#include<queue>
using namespace std;
#define maxn 2005
char mp[maxn][maxn];
int F[maxn],n,m,N;
vector<int>G[maxn];

int Find(int a){
    return F[a]==a?a:F[a]=Find(F[a]);
}
void bing(int a,int b){
    int c=Find(a),d=Find(b);
    if(c!=d)
        F[c]=d;
}

int main(){
    cin>>n>>m;N=n+m;
    for(int i=1;i<=N;i++)F[i]=i;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("
%c",&mp[i][j]);
            if(mp[i][j]=='=')
            bing(i,j+n);
        }
    for(int i=1;i<=N;i++)F[i]=Find(i);
        
    int d[maxn]={},in[maxn]={};
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(mp[i][j]=='>'){
                G[F[j+n]].push_back(F[i]);
                in[F[i]]++;
            }
            else if(mp[i][j]=='<'){
                G[F[i]].push_back(F[j+n]);
                in[F[j+n]]++;
            }
        }
    
    queue<int>q;
    int cnt=0;
    for(int i=1;i<=N;i++)
        if(in[i]==0){
            d[i]=1;
            cnt++;
            q.push(i);
        }
    
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(--in[v]==0){
                q.push(v);
                cnt++;
                d[v]=d[u]+1;
            }
        }        
    }
    
    if(cnt<N)puts("No");
    else {
        puts("Yes");
        for(int i=1;i<=n;i++)
            cout<<d[F[i]]<<" ";
        puts("");
        for(int i=n+1;i<=N;i++)
            cout<<d[F[i]]<<" ";
    }
} 
原文地址:https://www.cnblogs.com/zsben991126/p/10900767.html