poj 2912

并查集+扩展域好题

并查集+扩展域
题意有点模糊,意思是这里有三种人和一个判官在猜拳,每一种人只能出一种手势,这里面有一个判官可以随意改变自己的手势!给定m个回合判断,问判官是谁。能知道就输出最快能在第几回合清楚,如果多了就输出“Can not determine”,或者不存在就是“Impossible”。
分析:
数据很小,可以暴力枚举每一个人,如果n个人里面除开这个人以外,其余所有人都不冲突,则这个人就可能是判官,最后数一下有几个这样的人就好了,如果刚好只有一个,那么我们只需注意最快的回合;明显其余人不可能是判官的条件是出现了冲突,那么我们只需要输出其余所有人中冲突出现最晚的那个人就好了!
上代码:

#include<stdio.h>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<string.h>
using namespace std;
const int N = 5e2+5;
typedef long long ll;
// 0代表小于,1代表大于,2代表等于,判别方式(3-x)%3;
// 当每一次出现规则冲突时记录冲突数字,
int f[N],d[N],s[N];
int get(int x){
	if(f[x]==x){
		return x;
	}
	int cur=get(f[x]);
	d[x]=(d[x]+d[f[x]])%3;
	return f[x]=cur;
}
bool join(int p,int q, int fg){
	int l=get(p),r=get(q);
	if(l==r){
	if((d[p]+fg)%3==d[q]) return true;//网上大佬判冲突的。。。
		/*
		if(fg==0){
			if(d[p]==d[q]) return true;
		}
		else if(fg==1){
			if(d[p]==2&&d[q]==0) return true;
			if(d[p]==1&&d[q]==2) return true;
			if(d[p]==0&&d[q]==1) return true;
		}
		else{
			if(d[p]==1&&d[q]==0) return true;
			if(d[p]==2 &&d[q]==1) return true;
			if(d[p]==0&&d[q]==2) return true;
		}
		*/ //这个是我冲突。。。
		return false;
	}
	else{
		f[r]=l;
		d[r]=(fg+3-d[q]+d[p])%3;
		return true;
	}
}
int main()
{
	int n,m,i,j,k;
	char b[2001];
	int a[2001],c[2001];
	while(scanf("%d %d",&n,&m)==2){
		if(m==0){
			if(n==1){
				printf("Player 0 can be determined to be the judge after 0 lines\n");
			}
			else printf("Can not determine\n");
			continue;
		}
		int flag=0,ans=-1,pos=-1,cnt=0,kk=0;
		for(i=0;i<=n;i++) f[i]=i,d[i]=0;
		for(i=1;i<=m;i++){
			scanf("%d%c%d",&a[i],&b[i],&c[i]);
		}
		for(i=0;i<n;i++){
			for(k=0;k<=n;k++) f[k]=k,d[k]=0;
			cnt=0;
			for(j=1;j<=m;j++){
				if(b[j]=='=') k=0;
				else if(b[j]=='>') k=1;
				else k=2;
				if(a[j]==i||c[j]==i) continue;
				if(!join(a[j],c[j],k)){
					cnt++;
					pos=max(pos,j);
					break;
				}
			}
			kk+=(cnt==0);
			if(cnt==0) ans=i;
		}
		if(kk==0){
			printf("Impossible\n");
		}
		else{
			if(kk>1){
				printf("Can not determine\n");
			}
			else{
				printf("Player %d can be determined to be the judge after %d lines\n",ans,pos);
			}
		}
	}
	return 0;
}

自言自语

最近算法忘得有点狠,这个寒假集训就用来复习算了,这是寒假第一题,并查集写wa了,正确的并查集扩展域写法应该是先递归到最底层然后一路向上更新路径,而正确的并查集边带权则是

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值