poj 1182 食物链 并查集
2015-10-25 15:04
405 查看
食物链
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
只有一个整数,表示假话的数目。
Sample Input
Sample Output
Source
Noi 01
汗,在网上搜索,看了半天的带权并查集,看不懂,看了学妹的代码看懂了,
有n个动物,对于每个动物k,设food[k]=k+i,food[k+i]=k+2i;food[k+2*i]=i;这样就构成了一条循环食物链。
一共有三种动物,如果知道了两个动物是一种那么可以合并(并查集基本操作),并将他们对应的 food(被捕食者)和(捕食者)
合并。
代码上有注释,很容易看懂:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 55072 | Accepted: 16149 |
动物王国中有三类动物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
只有一个整数,表示假话的数目。
Sample Input
100 7 1 101 1 2 1 2 2 2 3 2 3 3 1 1 3 2 3 1 1 5 5
Sample Output
3
Source
Noi 01
汗,在网上搜索,看了半天的带权并查集,看不懂,看了学妹的代码看懂了,
有n个动物,对于每个动物k,设food[k]=k+i,food[k+i]=k+2i;food[k+2*i]=i;这样就构成了一条循环食物链。
一共有三种动物,如果知道了两个动物是一种那么可以合并(并查集基本操作),并将他们对应的 food(被捕食者)和(捕食者)
合并。
代码上有注释,很容易看懂:
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #include<climits> #include<queue> #include<vector> #include<map> #include<sstream> #include<set> #include<stack> #include<cctype> #include<utility> #pragma comment(linker, "/STACK:102400000,102400000") #define PI 3.1415926535897932384626 #define eps 1e-10 #define sqr(x) ((x)*(x)) #define FOR0(i,n) for(int i=0 ;i<(n) ;i++) #define FOR1(i,n) for(int i=1 ;i<=(n) ;i++) #define FORD(i,n) for(int i=(n) ;i>=0 ;i--) #define lson num<<1,le,mid #define rson num<<1|1,mid+1,ri #define MID int mid=(le+ri)>>1 #define zero(x)((x>0? x:-x)<1e-15) #define mk make_pair #define _f first #define _s second using namespace std; //const int INF= ; typedef long long ll; //const ll inf =1000000000000000;//1e15; //ifstream fin("input.txt"); //ofstream fout("output.txt"); //fin.close(); //fout.close(); //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); const int INF =0x3f3f3f3f; const int maxn= 50000+20 ; //const int maxm= ; /* 总结: 一共有n个动物,这里虚拟出了2*n个,最后一共有3*n个,把每个动物x都虚拟出一个相应的食物food[x]和捕食它的动物food[food[x]], 这样对于x,虚拟本身出来的动物food[x]和food[food[x]]本身和x不产生矛盾, 会让我们方便解题。 */ int pre[3*maxn],food[3*maxn]; int a[3],b[3]; int n,N,ans;//n动物种数、N虚拟的3*n种动物,ans 答案(假话数) int find(int x) { return x==pre[x]? x :pre[x]=find(pre[x]); } void samegroup(bool same,int x,int y)//如果D==1 {//这句话说他们是同种动物 if(same)//如果两者之前的食物链合并过 { if(a[0]!=b[0]) ans++;//如果x、y的代表动物不一样,这句话是假话。 return ; } for(int i=0;i<3;i++)//如果两者之前的食物链没有合并过 { pre[b[i]]=a[i];//food和捕食者 对应合并 } } void different(bool same ,int x,int y)//如果D==2 { if(x==y) {ans++ ; return ;}//说x、y不是同种动物,但是x、y又一样,是假话 if(same)//如果两者之前的食物链合并过 { if(a[1]!=b[0]) ans++;//这个时候x的食物代表动物a[1]应该和y的代表动物b[0]一样,否则假话 return; } for(int i=0;i<3;i++) { pre[b[i]]=a[(i+1)%3];//对应合并 } } void work() { int rela,x,y; scanf("%d%d%d",&rela,&x,&y); if(x>n||y>n) {ans++;return ;}//动物序号 > 大于动物个数,假话 a[0]=find(x);a[1]=find(food[a[0]] );a[2]=find(food[a[1]] );//取x所在食物链的三个代表动物 b[0]=find(y);b[1]=find(food[b[0]] );b[2]=find(food[b[1]] );//取y所在食物链的三个代表动物 bool same=false; for(int j=0;j<3;j++) { if(a[0]==b[j]) {same=1;break;} }//如果same==1,那么证明x、y所在的食物链已经合并过了,只需要判断真假 if(rela==1) samegroup(same,x,y);//如果D==1 else different(same,x,y);//如果D==2 } void init() { ans=0; for(int i=1;i<=N;i++) pre[i]=i; for(int i=1;i<=n;i++) { food[i]=i+n; food[i+n]=i+2*n; food[i+2*n]=i; } } int main() { int k; scanf("%d%d",&n,&k); N=3*n; init(); for(int i=1;i<=k;i++) { work(); } printf("%d\n",ans); return 0; }
相关文章推荐
- HDU 1114 Piggy-Bank 完全背包变形
- 设计模式——策略模式_2
- Struts2 和spring整合的 Action层托管问题
- 有关栈溢出漏洞的利用
- * &
- [ARM7--LPC2478]Memory Map
- z-index:9999在CSS中是什么意思
- 1016. 部分A+B (15)
- HDU 3364 Lanterns (高斯消元解开关问题)
- js引用类型之Object类型
- Linux中网络编程常用函数
- 树的直径与重心
- 软考系列——求最优算法盘点
- 举例讲解JavaScript中将数组元素转换为字符串的方法
- 过河卒
- web前端之HTML常用标签,元素,属性
- Qt shortcuts
- cf 15a Cottage Village
- gdb简单应用
- win7安装ubuntu双系统,建议使用u盘安装