【K - Rochambeau】

思路:

  • 带权并查集+枚举
  • 关键在题意:
    1. 若按照一般做法,当出现矛盾时完全无法判断是关系链上的哪一环导致出错,也就无法确定 judge 的身份。
    2. 枚举每一个人,认为此人是 judge 时,有关他的所有关系都是不可信的,需要跳过
    3. 题目不仅要求出谁是 judge,还要求判断多少条关系后能够确认他是 judge,等价于能够判断所有其他人都不是 judge 的语句数量。
    4. 所以,EDGE 存边枚举 judge 得到 ans[0…N)cnt 存 ans[i]==0的 i 的数量(cnt=0:impossible 不符合题意;cnt=1:找到 judge;cnt>1:条件不全导致无法确定 judge)。

代码:

  • 329ms 720kB
​//329ms		720kB


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 505;

int N,M;
int ans[maxn];int cnt;
int par[maxn];
int val[maxn];
struct EDGE{
	int l,r,w;
}edge[maxn * 4];
void ADDEDGE(int m,int w,int l,int r){
	edge[m].l = l;
	edge[m].r = r;
	edge[m].w = w;
	return ;
}

void INIT(){
	memset(par , -1 , sizeof(par));
	memset(val , 0 , sizeof(val)) ;
	return ;
}

int FIND(int i){
	if(par[i] == -1)
		return i;
	int tp = par[i];
	par[i] = FIND(par[i]);
	val[i] = (val[i] + val[tp]) % 3;
	return par[i];
}

void UNION(int w,int l,int r,int parl,int parr){
	par[parr] = parl;
	val[parr] = (val[l] + w - val[r] + 3) % 3;
	return ;
}

int main(){
	while(cin>>N>>M){
		cnt = 0;
		memset(ans , 0 , sizeof(ans));
		for(int m=1;m<=M;m++){
			int l,r,w;
			char op;
			scanf("%d%c%d" , &l , &op , &r);
			if(op == '>')
				w = 1;
			else if(op == '=')
				w = 0;
				else
					w = 2;
			ADDEDGE(m , w , l , r);
		}
		for(int i=0;i<N;i++){
			//judge = i
			INIT();
			for(int m=1;m<=M;m++){
				int l = edge[m].l;
				int r = edge[m].r;
				int w = edge[m].w;
				if(l == i || r == i)
					continue;
				int parl = FIND(l);
				int parr = FIND(r);
				if(parl == parr){
					if((val[l] + w) % 3 != val[r]){
						ans[i] = m;
						break;
					}
				}
				else
					UNION(w , l , r , parl , parr);
			}
		}
		int id;
		for(int i=0;i<N;i++)
			if(!ans[i]){
				cnt++;
				id = i;
			}
		if(!cnt){
			//去了哪个,剩下的都会出现矛盾,impossible 
			printf("Impossible\n"); 
		}
		else if(cnt == 1){
			//got it
			int tp = 0;
			for(int i=0;i<N;i++)
				tp = max(tp , ans[i]);
			printf("Player %d can be determined to be the judge after %d lines\n" , id , tp);
		}
			else{
				//去了一些,剩下的都没有矛盾,ambiguous 
				printf("Can not determine\n");
			}
	}
	return 0;
}​

猜你喜欢

转载自blog.csdn.net/flash403/article/details/94646416
k