[kuangbin带你飞]专题五 并查集 poj2912(种类并查集->带权并查集+暴力枚举)

K - RochambeauPOJ - 2912

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题意:

  1. 叫你找出裁判,即一直变的人。
  2. 其他方面类似“ 食物链POJ - 1182

(题外话:)

  1. 一开始操作还是和食物链差不多,但是本题可能有多个裁判(impossible的情况)所以很难操作。
  2. 一开始直接取判断,写了一大堆逻辑语句,白给了一天。
  3. 后面看了题解:(mmp)n只有500,小的要命。直接暴力。

思路(枚举)

  1. 先枚举每个人都可能成为教练,根据题目要求,最多只有一个教练。
  2. 所以当i是裁判,关于和i有关的询问都要忽略(comntinue),如果此时出现矛盾(类似食物链),那么break,
  3. if(看现在访问到最后一次询问后)那么没矛盾(既然能询问完,不break,那么说明i是裁判,去掉i,其他的关系都是正确的,更新ans)
  4. 具体看代码

思路

  1. 写了一天bug,白给了一天qwq
    在这里插入图片描述
  2. 对于题目数据小的题,应该要想到枚举。反思qwq
  3. 并查集种类的模板(记得都要加模,且反过来,具体还是依题目而定)
//find函数
int find(int x)
{
 	if(x==f[x])return x;
	int root=find(f[x]);
 	dis[x]=(dis[x]+dis[f[x]])%mod;//记得加模
   	return f[x]=root;
}


//merge
if((dis[a[j]]-dis[b[j]]+mod)%mod!=op[j]){
      tmp=max(j,tmp);
      break;
}else{
       f[A]=B;
       dis[A]=(dis[b[j]]-dis[a[j]]+op[j]+mod)%mod;
}
  1. 字符输入时可以这样
scanf("%d%c%d",&x,&ch,&y);

AC

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
const int maxn=5e2+10;
const int maxm=2e3+10;
const int mod=3;
int f[maxn], dis[maxn],a[maxm],b[maxm],op[maxm];
char ch;
int n,m;
int find(int x)
{
    if(x==f[x])return x;
    int root=find(f[x]);
    dis[x]=(dis[x]+dis[f[x]])%mod;
    return f[x]=root;
}
void init()
{
    For(i,1,m)
    {
        int x,y;
        scanf("%d%c%d",&x,&ch,&y);
        a[i]=x;
        b[i]=y;
        if(ch=='=')op[i]=0;
        else if(ch=='>')op[i]=1;
        else op[i]=2;
    }
}
int main()
{
    while(~scanf("%d%d", &n,&m))
    {
        init();
        int flag=0,ans=-1,tmp=0;
        For(i,0,n-1)
        {
            For(j,0,n-1)f[j]=j,dis[j]=0;
            int j;
            for(j=1; j<=m; j++)
            {
                if(a[j]==i||b[j]==i)continue;
                int A=find(a[j]);
                int B=find(b[j]);
                if(A==B)
                {
                    if((dis[a[j]]-dis[b[j]]+mod)%mod!=op[j])
                    {
                        tmp=max(j,tmp);//用一种更新把矛盾点时时更新。并取到最大
                        break;
                    }
                }
                else
                {
                    f[A]=B;
                    dis[A]=(dis[b[j]]-dis[a[j]]+op[j]+mod)%mod;
                }
            }
            if(j==m+1)
            {
                if(ans==-1){flag=1;ans=i;}
                else {flag=2;break;}//对于2次都找不到矛盾的,说明里面没裁判
            }
            //细心的读者要发现,跑完整个for是为了找到max line
        }
       if(ans== -1)printf("Impossible\n");//如果一直都矛盾,那么裁判的数肯定大于等于2.
        else if(flag==1)printf("Player %d can be determined to be the judge after %d lines\n",ans,tmp);
        else if (flag==2)printf("Can not determine\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值