cf1131 D. Gourmet choice(并查集处理连通块+拓扑排序)
题意:
构造正整数数组 ,要求用到的最大数尽量小。对任意 , 和 的大小关系已知。
数组大小均小于1000
思路:
先处理所有相等关系。用并查集,把相等的元素放进同一连通块中,得到 idx 个连通块
然后处理所有不等关系。若 ,则从 所在的连通块向 所在的连通块连边。对所有连通块做拓扑排序,一边排序一边填数(染色)。
图中可能有重边、反边、环,图也不一定连通,但都不用特殊处理。只在拓扑排序后判断就行。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5, M = 2 * N;
int n, m, p[M], idx, id[M], in[M], col[M], ans[M];
char a[N][N]; //输入
vector<int> blo[M], ne[M]; //ne存图
int get(int x) {return (x==p[x]?x:(p[x]=get(p[x]))); }
int q[M];
bool topo()
{
int hh = 0, tt = -1;
for(int i = 1; i <= idx; i++) if(!in[i])
q[++tt] = i, col[i] = 1; //给连通块染色
while(hh <= tt) {
int u = q[hh++];
for(int v : ne[u]) if(--in[v] == 0)
q[++tt] = v, col[v] = col[u] + 1;
}
return tt == idx - 1; //有无拓扑序
}
signed main()
{
for(int i = 1; i < M; i++) p[i] = i; //init
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) {
scanf(" %c", &a[i][j]);
if(a[i][j] == '=') p[get(i)] = get(j+n); //合并相等元素
}
for(int i = 1; i <= n; i++) { //处理出连通块
int fa = get(i);
if(!id[fa]) id[fa] = ++idx; //记录每个祖先所在的连通块
blo[id[fa]].push_back(i);
}
for(int i = 1; i <= m; i++) {
int fa = get(i+n);
if(!id[fa]) id[fa] = ++idx;
blo[id[fa]].push_back(i+n);
}
for(int i = 1; i <= n; i++) //建图,记录入度
for(int j = 1; j <= m; j++) {
int bi = id[get(i)], bj = id[get(j+n)];
if(a[i][j] == '<') ne[bi].push_back(bj), in[bj]++;
if(a[i][j] == '>') ne[bj].push_back(bi), in[bi]++;
}
if(!topo()) return puts("No"), 0;
for(int i = 1; i <= idx; i++) for(int j : blo[i]) ans[j] = col[i];
puts("Yes"); for(int i = 1; i <= n; i++) printf("%d ", ans[i]);
puts(""); for(int i = 1; i <= m; i++) printf("%d ", ans[i+n]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现