HDU-1811 Rank of Tetris

拓扑排序难题。

对于相同排名的玩家,我们将他们组成一个集合。这可以用并查集实现。

然后将并查集看成一个点,将所有大于小于的关系转换成集合中的关系,这个过程就可以判断方案是否冲突了。

然后拓扑排序求排名,顺便也就可以判断结果是否唯一了。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cctype>
#include <queue>
#include <cstring>
#include <queue>
using namespace std;
#define rep(i, l, r) for(int i=l; i<=r; i++)
#define travel(x) for(edge *p=fir[x]; p; p=p->n)
#define maxn 10009
#define maxm 20009
#define clr(x, c) memset(x, c, sizeof(x))

struct edge{int x, y, z; edge *n;} e[maxm], *fir[maxn], *pt;
int n, m, a, b, v[maxn], h[maxn], die;
char s[10];
inline void Init(){pt=e; clr(fir, 0); clr(v, 0); die=0; rep(i, 0, n-1) h[i]=i;}
inline void Add(int x, int y, int z){pt->x=x, pt->y=y, pt->z=z, pt++;}
int Find(int x){return x==h[x]?x:h[x]=Find(h[x]);}
int main()
{
	while (~scanf("%d%d", &n, &m))
	{
		Init();
		rep(i, 0, m-1)
		{
			scanf("%d%s%d", &a, s, &b);
			if (s[0]=='=') Add(max(a, b), min(a, b), 0);
			else if (s[0]=='>') Add(a, b, 1);
			else if (s[0]=='<') Add(b, a, 1);
		}
		rep(i, 0, m-1) if (!e[i].z) 
			Find(e[i].x)!=Find(e[i].y) ? h[h[e[i].x]]=h[e[i].y] : i=i;
		rep(i, 0, n-1) Find(i);
		
		priority_queue<int>q;
		rep(i, 0, m-1) if (e[i].z) e[i].x=h[e[i].x], e[i].y=h[e[i].y];
		rep(i, 0, m-1) if (e[i].z) v[e[i].y]++;
		rep(i, 0, m-1) if (e[i].z) e[i].n=fir[e[i].x], fir[e[i].x]=&e[i];
		rep(i, 0, n-1) if (h[i]==i && !v[i]) q.push(i);
		while (!q.empty())
		{
			if (q.size()>1) die=2;
			int x=q.top(); q.pop(); v[x]=-1;
			travel(x) if (p->z) {v[p->y]--; if (!v[p->y]) q.push(p->y);}
		}
		rep(i, 0, n-1) if (h[i]==i && v[i]!=-1) {die=1; break;}
		if (die==0) printf("OK
"); 
		else if (die==1) printf("CONFLICT
");
		else printf("UNCERTAIN
"); 
	}
}

  

原文地址:https://www.cnblogs.com/NanoApe/p/4445331.html