POJ 1182 食物链

来源:互联网 发布:暴风集团域名 编辑:程序博客网 时间:2024/06/07 05:20

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

题意:巧妙的利用关系之间的可加性。例如:a吃b,parent[a] = b,r[a] = 1,b吃c,parent[b] = c,r[b] = 1.因为a吃b,b吃c,所以c一定吃a即如果更新paret[a] = c,r[a] = r[a]+r[b] = 2,即c吃a. 其他情况也证明可以累加。如果超过3的话就模3,为负数的话就加上3在模三。

貌似这种算法只有这题能用,假如有四种生物的话就不知道行不行了,╮(╯▽╰)╭

#include<stdio.h>#include<string.h>#include<stdlib.h>#define INF 51000int n,k;int parent[INF],r[INF];//r[i]==1代表i能吃parent[i],2代表parent[i]吃i,0代表i和parent[i]同类int root(int x){if(parent[x] == -1)return x;else{int temp = parent[x];parent[x] = root(parent[x]);r[x] = (r[x]+r[temp])%3;//路径压缩,更新节点对根的关系值return parent[x];}}void merge(int x,int y,int rel){int temp1 = root(x),temp2=root(y);parent[temp1] = temp2;r[temp1] = (3 + rel-r[x]+r[y])%3;//把两个根合并,虽然temp1的子节点没有更新parent和r,但是后面一旦再次出现子节点,就会更新了}int main(){scanf("%d%d",&n,&k);//仅有一个用例,,,memset(r,0,sizeof(r));memset(parent,-1,sizeof(parent));int order,x,y,ans = 0;for(int i = 1;i <= k ; i ++){scanf("%d%d%d",&order,&x,&y);if( x > n || y > n || (order == 2 && x == y) ){ans ++;continue;}int a = root(x);//找x的根节点,顺带更新该节点int b = root(y);if(a != b){if(order == 1)merge(x,y,0);if(order == 2)merge(x,y,1);}else{if(order == 1){if(r[x] != r[y])ans++;}if(order == 2){if((r[x]-r[y] + 3)%3!= 1)//上面每次merge都是把y作为x的根节点,这里就是//x->y = x->a(即r[x]) + a->y(即-r[y]);ans++;}}}printf("%d\n",ans);return 0;}


 

原创粉丝点击