【#|HDU1811 Rank of Tetris——拓扑排序(BFS+并查集)】点这里
题意: n个人个m个约束条件,每行约束条件都有“<>=”符号,“=”表示两人同级,两个人之间编号大的在前。按照已知条件如果排名唯一,则输出OK;排名不唯一则输出UNCERTAIN;约束条件之间矛盾则输出CONFLICT。
题解:
- 缩点(并查集)。 不要想 的太复杂 (我就是一直在考虑“=”怎么处理,一直没敢下手) 其实所有
=
联系的点,合并成一个点处理即可,他们内部的排名肯定是能够确认的,题目不要求输出排名,那就不用在意,看成一个点处理就行。这步处理,则是采用并查集的方式。 - CONFLICT。 什么样情况下会矛盾,其实应该说条件矛盾会造成什么后果。一种情况是同时出现
a = b
和a > b
,这个很容易判断,一开始读入的时候,就可以将所有“=”的两个点合并,之后再遍历每一条边,检查是否有冲突。第二种情况 是出现a > b
和a < b
的环,造成的后果是拓扑排序的BFS中,出现一些点的入度不为零,无法入队,这种情况只要跑完一遍BFS检查是否还要入度不为零的点即可。 - UNCERTAIN。 想一下什么条件可能造成最后排名不唯一,可一句样例
1 > 0, 1 > 2, 2 < 1
,如果去掉重边,观察0、1、2三个点的入度分别为0、1、1。也就是说再遍历点1的边时,0和2的入度会同时减为0,并且入队。即如果在BFS排序过程中,队列中出现了两个及以上的元素,说明最终排名可能不唯一。
- sum可能为负。 虽然进行了缩点,,但实际上的点数没有改变。(sum的初始值为n,程序中每出现一次“=”,sum就会减一;每当一个点入队,sum就会减一),进行过缩点操作之后,我的程序中认可的点可能只有x个,但是出现的点可能一共会有n个,n如果>x,sum会出现负数。所以检查是否所有(认可的)点都入队,应判断最后的sum>0?而不是判断sum==0?
- BFS函数必须完整执行。 一开始我一旦找到队列中包含两个及以上的元素,说明最后排名可能不唯一的时候,我写了一个
return
。实际上如果这个函数不执行完的话,还会影响sum的结果,而sum的结果先影响了是否输出UNCERTAIN。因此这里不能return
。
#include
using namespace std;
const int N = 1e4 + 10;
int n, m, sum;
int deg[N], s[N];
bool flag, sign;
vector v[N];
struct edge{ int x, y;
char c;
}e[2 * N];
int find(int x){ return s[x] == x? x: s[x] = find(s[x]);
}
void un(int a, int b){ int sa = find(a), sb = find(b);
if(sa != sb) s[sa] = sb;
}
void check(){
for(int i = 0;
i < m;
i++){
if(e[i].c == '=') continue;
int a = find(e[i].x), b = find(e[i].y);
if(a == b){ flag = false;
return;
}
if(e[i].c == '<'){
deg[a]++;
v[b].push_back(a);
}else{
deg[b]++;
v[a].push_back(b);
}
}
}
void BFS(){
queue q;
for(int i = 0;
i < n;
i++){
int a = find(i);
if(!deg[a] && s[a] == i) q.push(a);
}
while(!q.empty()){
int a = q.front();
q.pop();
sum--;
if(!q.empty()) sign = false;
//不能return
for(int i = 0;
i < v[a].size();
i++){
int b = v[a][i];
deg[b]--;
if(!deg[b]) q.push(b);
}
}
}
int main(){
while(~scanf("%d%d", &n, &m)){
sum = n;
flag = sign = true;
for(int i = 0;
i < n;
i++) deg[i] = 0, s[i] = i, v[i].clear();
//init();
for(int i = 0;
i < m;
i++){
scanf("%d %c %d", &e[i].x, &e[i].c, &e[i].y);
if(e[i].c == '=') un(e[i].x, e[i].y), sum--;
}
check();
BFS();
if(sum > 0 || !flag)printf("CONFLICT\n");
//不能 sum != 0
else if(!sign)printf("UNCERTAIN\n");
elseprintf("OK\n");
}
return 0;
}
推荐阅读
- 数据结构和算法|LeetCode 的正确使用方式
- #|7.分布式事务管理
- #|算法设计与分析(Java实现)——贪心算法(集合覆盖案例)
- #|算法设计与分析(Java实现)—— 动态规划 (0-1 背包问题)
- #|阿尔法点亮LED灯(一)汇编语言
- #|Multimedia
- #|ARM裸机开发(汇编LED灯实验(I.MX6UL芯片))
- 基础课|使用深度优先搜索(DFS)、广度优先搜索(BFS)、A* 搜索算法求解 (n^2 -1) 数码难题,耗时与内存占用(时空复杂度)对比(附((n^2 - 1) 数码问题控
- #|学习笔记 | Ch05 Pandas数据清洗 —— 缺失值、重复值、异常值
- win10|搏一搏 单车变摩托,是时候捣鼓一下家中的小米电视机啦。