并查集——POJ 1182 食物链

  • 题目链接:http://poj.org/problem?id=1182

  • 题意:给出N只动物,它们属于A,B,C三种类型,其中A吃B,B吃C,C吃A,接下来给出K句话描述它们的关系:一种是 1,x,y 表示x,y是属于一类,另一种 2,x,y 表示x吃y。某一句话为假,当且仅当,x或者y超出范围,或者 x等于y,或者这句话和前面的真话矛盾,求假话的数量

  • 分析:这里一共要维护两种关系:捕食关系和归属关系。刚开始,我们可能会想到设定给每一种动物判定一种类型,通过判断这些动物属于的类型是否构成矛盾来计算假话的数量。不过很快,我们就发现我们并不能确定每一种动物的类型!为之奈何?我有很无奈啊,那既然不知道它属于哪一种,那我们就把同时计算它属于每一种的情况,每次更新这三个类型,如果其中一种情况出了问题,那么肯定就是假的了(这个仔细想想,可以发现时必然成立的)

  • 具体做法:如果x,y属于同一类,那么x-a和y-a,x-b和y-b,x-c与y-c都更新为同一类;如果x捕食y,那么x-a捕食y-b,x-b捕食y-c,x-c捕食y-a。这样就可以安心玩并查集了

  • AC代码:

/*************************************************************************
    > File Name: test.cpp
    > Author: Akira 
    > Mail: qaq.febr2.qaq@gmail.com 
 ************************************************************************/

#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <ctime>
#include <climits>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;

#define MaxN 200010
#define MaxM MaxN*10
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
const int mod = 1E9+7;
const double eps = 1e-6;
#define bug cout<<88888888<<endl;
#define debug(x) cout << #x" = " << x;
int N,K;
int fa[MaxN];
int getfather(int x)
{
    int fx=fa[x];
    if(fx!=x) 
    {
        fx=getfather(fa[x]);
    }
    return fa[x]=fx;
}
void U(int x,int y){
    int fx=getfather(x),fy=getfather(y);
    if(fx!=fy) fa[fy]=fx;
}
int main()
{
    //std::ios::sync_with_stdio(false);
    scanf("%d%d", &N, &K);
    for(int i=1;i<=3*N;i++){
        fa[i]=i;
    }
    int ans = 0;
    int type,x,y;
    while(K--)
    {
        scanf("%d%d%d", &type, &x, &y);
        if(x<0||x>N||y<0||y>N||(type==2&&x==y)) 
        {
            ans++;
            continue;
        }
        if(type==1)
        {
            // A  B   C
            // x  x+N x+2N
            // y  y+N y+2N
            int fx = getfather(x);
            int fy1 = getfather(y+N);
            int fy2 = getfather(y+2*N);
            if( fx == fy1 || fx == fy2) ans++;
            else{
                U(x,y);
                U(x+N, y+N);
                U(x+2*N, y+2*N);
            }
        }
        else
        {   
            int fx = getfather(x);
            int fy1 = getfather(y);
            int fy2 = getfather(y+2*N);
            if( fx == fy1 || fx == fy2) ans++;
            else{
                U(x,y+N);
                U(x+N, y+2*N);
                U(x+2*N, y);
            }
        }
    }
    printf("%d\n", ans);
    //system("pause");
}
内容概要:《学术研究提示设计 50 招》是一份详尽的指南,旨在帮助研究人员提高学术写作和研究效率。该文档涵盖了从论文撰写、润色、翻译、查重降重、参考文献管理、投稿审稿到文献阅读等多个方面的具体操作指令。每一章节均针对特定任务提供了详细的步骤和注意事项,例如如何撰写标题、摘要、致谢,如何进行英文润色、中英翻译,以及如何优化逻辑结构等。文档还介绍了如何利用AI工具进行文献分析、术语表提取和研究方向探索等内容,为研究者提供了全面的支持。 适合人群:适用于学术研究人员,特别是那些需要撰写、润色和提交学术论文的研究者,包括研究生、博士生及高校教师等。 使用场景及目标:① 提供一系列具体的指令,帮助研究者高效完成论文的各个部分,如撰写标题、摘要、致谢等;② 提供润色和翻译的详细指导,确保论文语言的准确性和专业性;③ 提供查重降重的方法,确保论文的原创性;④ 提供参考文献管理和投稿审稿的指导,帮助研究者顺利发表论文;⑤ 利用AI工具进行文献分析、术语表提取和研究方向探索,提高研究效率。 阅读建议:此资源不仅提供了具体的指令和方法,更重要的是引导研究者如何思考和解决问题。因此,在学习过程中,不仅要关注具体的步骤,还要理解背后的原理和逻辑,结合实际案例进行实践和反思。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值