专栏文章

题解:CF1131D Gourmet choice

CF1131D题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miosqm49
此快照首次捕获于
2025/12/03 00:32
3 个月前
此快照最后确认于
2025/12/03 00:32
3 个月前
查看原文

题意

构造序列 a,ba,b,满足每个 ai,bja_i,b_j 之间的大小关系。

题解

考虑拓扑排序,把小的向大的连边,如果相等就用并查集并到一起。
答案记录在 ans 数组里。
从最小的开始(入度为 00),让 ansi=1ans_i=1,之后每一对 uvu \to vansv=ansu+1ans_v=ans_u+1,因为一个点要同时满足多个条件,所以要取一个最大值。
记录一个 vis 数组,把所有的遍历到的点记录下来,最后如果有点没有被遍历过就输出 No。
否则输出答案。
要注意因为用并查集合并了相等的点,所以实现的时候都要用并查集里的编号。

代码

CPP
#include<bits/stdc++.h>
#define int long long
#define double long double
#define bug cout<<"___songge888___"<<'\n';
using namespace std;
int n,m;
vector<int> g[2111];
int fa[2111];
int vis[2111];
int in[2111];
char c[1111][1111];
int ans[2111];
int Find(int x){
    return fa[x]==x ? x :Find(fa[x]);
}
void merge(int x,int y){
    fa[Find(x)]=Find(y);
}
void topu(){
    queue<int> q;
    for(int i=1;i<=n+m;i++){
        if(fa[i]==i&&!in[i]){
            q.push(i);
            ans[i]=1;
			vis[i]=1;
        }
    }
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(auto v:g[u]){
			in[v]--;
            ans[v]=max(ans[v],ans[u]+1);
            if(!in[v]){
                vis[v]=1;
                q.push(v);
            }
        }
    }
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    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];
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(c[i][j]=='='){
				merge(i,n+j);
			}
		}
	}
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
        	char k=c[i][j];
            if(k=='<'){
            	in[Find(n+j)]++;
                g[Find(i)].push_back(Find(n+j));
            }
            else if(k=='>'){
            	in[Find(i)]++;
                g[Find(n+j)].push_back(Find(i));
            }
        }
    }
    topu();
    for(int i=1;i<=n+m;i++){
        if(!vis[Find(i)]){
            cout<<"No"<<'\n';
            return 0;
        }
    }
    cout<<"Yes"<<'\n';
    for(int i=1;i<=n;i++){
        cout<<ans[Find(i)]<<' ';
    }
    cout<<'\n';
    for(int i=1;i<=m;i++){
        cout<<ans[Find(n+i)]<<' ';
    }
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...