Codeforces Round #541 (Div. 2)(並查集又稱dsu,拓撲排序)
#include<bits/stdc++.h>
using namespace std;
vector<int>g[2007];
int fa[2007],vis[2007],num[2007];
char s[2007][2007];
int find_(int x){
if(fa[x]==x)
return x;
return fa[x]=find_(fa[x]);//合並
}
void dfs(int u){
vis[u]=-1;//正數說明有環,0說明需要dfs,so將其置為負數
++num[u];//從環尾dfs每次給環尾+1
for(auto&i:g[u]){
if(!--vis[i])
dfs(i);
}
}
void addedge(int u,int v){
g[u].push_back(v);//建圖
vis[v]++;//打上標記
}
int main(){
int n,m;
scanf("%d%d",&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++)
if(s[i][j]==‘=‘)
fa[find_(i)]=find_(n+j);//縮點
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(s[i][j]==‘<‘)
addedge(find_(i),find_(n+j));//大的放後面
else if(s[i][j]==‘>‘)
}
int flag=0;
for(int i=1;i<=n+m;i++)
if(find_(i)==i&&!vis[i])//找一個代表與它同值的所有點的點並且沒有被拜訪過即鏈尾
dfs(i);//dfs
for(int i=1;i<=n+m;i++)
if(find_(i)==i&&vis[i]>0){//正值說明有環
flag=1;
printf("No");//顯然有環是不能安排的
break;
}
if(!flag){
printf("Yes\n");
for(int i=1;i<=n;i++)
printf("%d ",num[find_(i)]);//找到代表它的點的num值
printf("\n");
for(int i=1;i<=m;i++)
printf("%d ",num[find_(i+n)]);//找到代表它的點的num值
}
return 0;
}
Codeforces Round #541 (Div. 2)(並查集又稱dsu,拓撲排序)