Codeforces Round #541 (Div. 2) D. Gourmet choice //拓扑+并查集缩点
https://codeforces.com/contest/1131/problem/D
题意 未知a数组和b数组长度是m和n,给一个表示大小关系的矩阵 ,xij表示ai和bj的关系,求出最小的a和b(最小从1开始)。
自己有意识要先找到最小的,然后删去最小的影响,然后找第二小的,以此类推。
但是一直没想到利用拓扑排序构图,一直在数组上进行操作(WA了好几发)。
正确做法 利用并查集将‘=’的点集缩成一个树节点,在树节点上进行拓扑排序(可能多颗树),层次即为答案,最后将非树根节点跟新就可以k过这题。细节看注解。
自己还是做得题太少,感觉应该能想到拓扑的,今天这两题交20多发测试,
#include <bits/stdc++.h>
using namespace std;
int n,m;
char mp[1005][1005]; //原始图
int pre[2*1005]; //并查集 树根
int in[2*1005]; //入度
int ans[2*1005]; // answer
vector<int>g[2*1005];
struct no{int a,c;}; //bfs结点
int found(int x){
int re=x;
while(re!=pre[re]){
re=pre[re];
}
while(x!=pre[x]){
int t=pre[x];
pre[x]=re;
x=t;
}
return re;
}
void join(int x,int y){
int fx=found(x),fy=found(y);
if(fx!=fy) {
pre[fx]=pre[fy];
}
}
void addarc(int from,int to){
g[from].push_back(to);
in[to]++; //拓扑排序铺垫
}
void topo(int st){
queue<no>q;
q.push((no){st,1});
while(!q.empty()){
no now=q.front();q.pop();
ans[now.a]=now.c;
for(int i=0;i<(int)g[now.a].size();i++){
int to=g[now.a][i];
in[to]--;
if(in[to]==0) q.push((no){to,now.c+1});
}
g[now.a].clear();
}
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=0;i<n;i++)
cin>>mp[i];
int kk=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mp[i][j]!='='){
kk=1;
}
}
}
if(kk==0){ //kk==0 表示没有异点,不能topo 那么不会有1出现
cout<<"Yes"<<endl;
for(int i=0;i<m+n;i++){
cout<<1<<' ';
if(i==n-1) cout<<endl;
}
return 0;
}
for(int i=0;i<m+n;i++) pre[i]=i; //跟结点初始化
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mp[i][j]=='='){
join(i,j+n); //进行缩点
}
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(found(i)==found(j+n)&&mp[i][j]!='=') {
cout<<"No";return 0;
}
int fx=found(i),fy=found(j+n); //缩点进行构图
if(mp[i][j]=='>') {
addarc(fy,fx);
}
if(mp[i][j]=='<'){
addarc(fx,fy);
}
}
}
int i;
for(i=0;i<m+n;i++){
if(in[i]==0&&g[i].size()) {
topo(i); //多次拓扑是因为 可能会有多颗树
}
}
for(int i=0;i<m+n;i++){ //如果有环
if(in[i]!=0){
cout<<"No";return 0;
}
}
cout<<"Yes"<<endl;
for(int i=0;i<m+n;i++){
if(ans[i]==0){
ans[i]=ans[found(i)];
}
cout<<ans[i]<<' ';
if(i==n-1) cout<<endl;
}
return 0;
}