poj1182 食物链

不想多说什么了,这题虐我不浅,还是看完别人的解题报告的情况下。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int father[50001],relative[100001];
int n;
int find_ant(int c){
	if(father[c]!=c){
		int t=find_ant(father[c]);   //这一句和下一句不能颠倒,relative[]必须出现在find_ant()后,也就是说relative[]是在递归的回溯过程中建立的,这样才能保证relative[]对应的祖先节点是正确的。只有在祖先节点确定的情况才能计算relative[]。而relative[]出现在find_ant()前面时,先建立了relative[]和当前的祖先节点(并非最终确定的祖先节点),随后祖先节点又在递归中被改变,relative[]就不正确了。罗嗦了大半天,就一句,relative[]的建立一定出现在find_ant()之后。
		relative[c]=(relative[c]+relative[father[c]])%3;
		father[c]=t;
	}
	return father[c];
}
bool _union(int x,int y,int r){
    int px=find_ant(x);
    int py=find_ant(y);
    if(x>n||y>n) return true;
    if(px==py){
        if(relative[x]==relative[y]&&r==1) return false;
        if((relative[x]-relative[y]+3)%3==2&&r==2)
            return false;
        return true;
    }
    relative[py]=(3-relative[y]+r-1+relative[x])%3;
    father[py]=px;
    return false;
}
int main(){
    int k;
    int i;
    int x,y,g;
    int res=0;
    scanf("%d%d",&n,&k);
	for(i=1;i<=n;i++){
        father[i]=i;
		relative[i]=0;
	}
    while(k--){
        scanf("%d%d%d",&g,&x,&y);
        if(_union(x,y,g))
            res++;
    }
	printf("%d\n",res);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值