Description

动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。 
现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。 
有人用两种说法对这N个动物所构成的食物链关系进行描述: 
第一种说法是"1 X Y",表示X和Y是同类。 
第二种说法是"2 X Y",表示X吃Y。 
此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。 
1) 当前的话与前面的某些真的话冲突,就是假话; 
2) 当前的话中X或Y比N大,就是假话; 
3) 当前的话表示X吃X,就是假话。 
你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。 

Input

第一行是两个整数N和K,以一个空格分隔。 
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。 
若D=1,则表示X和Y是同类。 
若D=2,则表示X吃Y。

Output

只有一个整数,表示假话的数目。
我是 比如 A>B>C 对于每个点都有 P[X] V[X]表示 他被谁打败了  他打败了谁   他们之间的关系处理好后 比如A>B>C D>E>F  一旦 B 与E有关系 在不出错的前提下 然后 处理好 AD  BE CF之间的关系 
#include <iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int maxn=;
int per[maxn],p[maxn],v[maxn],N,K;
int fa(int a){ return per[a]=per[a]==a?a:fa(per[a]);}
bool jud1(int X,int Y){
if(X<||Y<||X>N||Y>N) return false;
int fx=fa(X),fy=fa(Y);
if(fx==p[fy]||fx==v[fy]||fy==p[fx]||fy==v[fx]) return false;
per[fy]=fx;
if(p[fx]!=&&p[fy]!=){ per[p[fy]]=p[fx];}
if(p[fx]==&&p[fy]!=)p[fx]=p[fy];
if(v[fx]!=&&v[fy]!=){ per[v[fy]]=v[fx];}
if(v[fx]==&&v[fy]!=) v[fx]=v[fy];
if(p[fx]!=){ p[p[fx]]=v[fx]; v[p[fx]]=fx; }
if(v[fx]!=){ p[v[fx]]=fx; v[v[fx]]=p[fx];}
return true;
}
bool jud2(int X,int Y){
if(X<||Y<||X>N||Y>N) return false;
int fx=fa(X),fy=fa(Y);
if(fx==fy||fx==v[fy]||fy==p[fx]) return false;
if(p[fy]!=)per[p[fy]]=fx;
if(v[fx]==)v[fx]=fy;
else per[fy]=v[fx];
if(p[fx]!=&&v[fy]!=) per[v[fy]]=p[fx];
if(p[fx]==&&v[fy]!=) p[fx]=v[fy];
if(p[fx]!=){ v[p[fx]]=fx;p[p[fx]]=v[fx];}
if(v[fx]!=){ p[v[fx]]=fx;v[v[fx]]=p[fx];} return true;
}
int main()
{
scanf("%d%d",&N,&K);
for(int i=;i<=N;i++){
per[i]=i; p[i]=v[i]=;
}
int num=;
for(int i=;i<K;i++){
int D,X,Y;
scanf("%d%d%d",&D,&X,&Y);
switch(D){
case : if(jud1(X,Y)==false) ++num; break;
case : if(jud2(X,Y)==false) ++num; break;
}
}
cout<<num<<endl; return ;
}

还有一种方法 带权并查集 队友说也可以

当 操作1 时 判断

1 这两个点在 同一个集合当中  他们到达 祖先的距离不同则出现错误 相同就正确

2 这两个点不在同一个集合当中 那么就得将这两个集合 合并 就是说 d[x]=(d[y]+d[fy])%3或者 d[y]=(d[x]+d[fx])%3 这样就保证了他们在一个集合当中的相同的位置 我们在并查集中做了一点小动作 保证了要修改的 d[fx] 或者d[fy] 为跟节点的子树 能够将相应的位置进行相应的改变

当操作2 时 判断

1 这两个的点在同一个集合当中 他们到达祖先的距离(d[x]+1)必须等于d[y] 否则就出现错误(因为我们保证了小的距离吃大的距离 自然最后记得模三)

2 这两个点在不懂得集合当中 那么也必须得河滨这两个集合 就是说 (d[x]+1)%3==(d[y]+d[fy])%3 可以推得 (d[x]+1-d[y]+3)==d[fy] 这样也保证了这两个点在相对的位置

#include <iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int maxn=;
int per[maxn],d[maxn];
int fin(int a){
if(per[a]==a)return a;
int t=per[a];
per[a]=fin(per[a]);
d[a]=(d[a]+d[t])%;
return per[a];
}
bool unionnode(int D,int x,int y){
int fx=fin(x),fy=fin(y);
if(D==){
if(fx==fy){ return d[x]==d[y]?true:false; }
if(d[x]==d[y]){ per[fy]=fx;return true;}
if(d[x]>d[y]){ d[fy]=(d[x]-d[y])%;per[fy]=fx; return true; }
d[fx]=(d[y]-d[x])%; per[fx]=fy; return true;
}
if(fx==fy){ return ((d[x]+)%)==d[y]?true:false; }
d[fy]=(d[x]-d[y]++)%;
per[fy]=fx;
return true;
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++){
per[i]=i;d[i]=;
}
int num=;
while(k--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(b>n||c>n||!unionnode(a,b,c)) num++;
}
printf("%d\n",num);
return ;
}

POJ 1182 并查集的更多相关文章

  1. POJ1703 && POJ2942 &&POJ 1182 并查集 这个做法挺巧妙

    Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 37242   Accepted: ...

  2. 食物链 POJ - 1182 (并查集的两种写法)

    这是一个非常经典的带权并查集,有两种写法. 1 边权并查集 规定一下,当x和y这条边的权值为0时,表示x和y是同类,当为1时,表示x吃y,当为2时,表示x被y吃. 一共有三种状态,如图,当A吃B,B吃 ...

  3. poj 1182 并查集高级应用

    C - 是谁站在食物链的顶端 Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:10000KB     ...

  4. poj 1984 并查集

    题目意思是一个图中,只有上下左右四个方向的边.给出这样的一些边, 求任意指定的2个节点之间的距离. 就是看不懂,怎么破 /* POJ 1984 并查集 */ #include <stdio.h& ...

  5. poj 1797(并查集)

    http://poj.org/problem?id=1797 题意:就是从第一个城市运货到第n个城市,最多可以一次运多少货. 输入的意思分别为从哪个城市到哪个城市,以及这条路最多可以运多少货物. 思路 ...

  6. POJ 2492 并查集扩展(判断同性恋问题)

    G - A Bug's Life Time Limit:10000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u S ...

  7. POJ 2492 并查集应用的扩展

    A Bug's Life Time Limit: 10000MS Memory Limit: 65536K Total Submissions: 28651 Accepted: 9331 Descri ...

  8. POJ 3228 [并查集]

    题目链接:[http://poj.org/problem?id=3228] 题意:给出n个村庄,每个村庄有金矿和仓库,然后给出m条边连接着这个村子.问题是把所有的金矿都移动到仓库里所要经过的路径的最大 ...

  9. poj 1733 并查集+hashmap

    题意:题目:有一个长度 已知的01串,给出多个条件,[l,r]这个区间中1的个数是奇数还是偶数,问前几个是正确的,没有矛盾 链接:点我 解题思路:hash离散化+并查集 首先我们不考虑离散化:s[x] ...

随机推荐

  1. Docker 容器管理:rancher

    Rancher:https://www.cnrancher.com/ 是一个开源的企业级全栈化容器部署及管理平台. 定位上和 K8s 比较接近,都是通过 web 界面赋予完全的 docker 服务编排 ...

  2. Ubuntu16.04双网卡主备配置

    前几日写了一篇Ubuntu14.04双网卡主备配置,没成想变化总是这么快,今日安装某软件,提示最匹配的ubuntu版本是16.04,作为一个码农能有什么办法,只能不断去适应变化.拥抱变化. 首先16. ...

  3. js模拟点击打开超链接

    js模拟点击打开超链接,页面上有一些锚文本,如果用 JS 批量在新窗口打开. jquery示例: <div class="link"> <a href=" ...

  4. thinkphp与php共享session

    在其他php页面添加如下代码即可 if (!session_id()) session_start(); 使用时 thinphp 使用 session('test','123'); $user_inf ...

  5. Linux查看及设置系统字符集

    查看正在使用的字符集 查看可以设置的字符集 locale -a 修改字符集 export LANG=zh_CN.gbk

  6. 洛谷P2216 理想的正方形

    题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: 第一行为3个整数,分别表示a,b,n的值 第二行至 ...

  7. 【技术开放日】msup携手HPE揭秘全球测试中心背后的12条技术实践

    保证软件产品质量是软件测试永恒的目标. 以控制为出发点的传统IT时代正在快速的向以激活生产力为目的的移动互联时代转变.这不仅是技术的升级,更是思想意识的巨大变革,也对软件技术的发展带来的更高的要求和更 ...

  8. .Net微服务架构之运行日志分析系统

    一.引言 .Net技术栈目前还没有像spring cloud相对完整一整微服务架构栈,随着业务发展系统架构演进,自行构建.Net技术体系的微服务架构,配套相关核心组件.因平台基于微服务架构方式研发,每 ...

  9. NBUTOJ 1643 - 阶乘除法 - [数学题]

    题目链接:https://ac.2333.moe/Problem/view.xhtml?id=1643 问题描述 输入两个正整数 n, m,输出 n!/m!,其中阶乘定义为 n!= 1*2*3*... ...

  10. Hdu1010Tempter of the Bone 深搜+剪枝

    题意:输入x,y,t.以及一个x行y列的地图,起点‘S’终点‘D’地板‘.’墙壁‘X’:判断能否从S正好走t步到D. 题解:dfs,奇偶性减枝,剩余步数剪枝. ps:帮室友Debug的题:打错了两个字 ...