POJ 1182 食物链

题目大意:中文

题目链接

注释代码:

/*                
 * Problem ID : POJ 1182 食物链    
 * Author     : Lirx.t.Una                
 * Language   : C           
 * Run Time   : 235 ms                
 * Run Memory : 400 KB                
*/ 

#include <memory.h>
#include <stdio.h>

//动物的最大数量
#define	MAXN	50001
//模3运算
#define	MOD3(x)	( (x) % 3 )

int		fath[MAXN];//并查集
char	rela[MAXN];//rela[i]表示i和父结点之间的关系
//0 --> i和fath[i]同类
//1 --> i吃fath[i]
//2 --> fath[i]吃i

int
find(int x) {

	int		fx;

	if ( x == fath[x] ) return x;

	fx = fath[x];
	find(fx);//路径压缩一下,保证fx和根之间的关系是正确的
	//通过x和fx之间的关系以及fx和根之间的关系来更新
	//x和根之间的关系
	rela[x] = MOD3(rela[x] + rela[fx]);

	return fath[x] = find(fx);//最后再对x进行路径压缩
}

int
main() {

	int		n, k;//动物数量和询问数量
	int		x, y;//临时接受动物编号
	int		fx, fy;//表示x、y的树根编号
	int		cmd;
	int		i;//计数变量

	int		fault;//假话数量

	scanf("%d%d", &n, &k);
	fault = 0;

	//初始化
	for ( i = 1; i <= n; i++ ) fath[i] = i;
	memset(rela, 0, sizeof(0));

	while ( k-- ) {
	
		scanf("%d%d%d", &cmd, &x, &y);
		
		//x < 1 || y < 1 || x > n || y > n,表示超出范围,不存在这样的动物
		//2 == cmd && x == y,表示不能自己吃自己
		//这是两种非常显然的错误情况,一眼就能判断出来的
		if ( x < 1 || y < 1 || x > n || y > n || ( 2 == cmd && x == y ) ) {
		
			fault++;
			continue;
		}

		cmd--;//转化成正确关系,即在程序中X吃Y用1表示
		fx = find(x);
		fy = find(y);

		if ( fx != fy ) {//表示x、y不在一个集合中
			//就表示x和y的关系还未确定
			//因此就要将x、y所在集合合并并考察两者的关系
		
			fath[fy] = fx;//fy接在fx上
			//则fy和fx之间的关系需要更新,此更新方式可以通过枚举总结出
			rela[fy] = MOD3(rela[x] - rela[y] + cmd + 3);
		}//否则两者关系是已经确定的,则需要考察cmd是否能正确反映x和y之间的关系
		else if ( MOD3(rela[y] - rela[x] + 3) != cmd ) fault++;//不能反映
	}

	printf("%d\n", fault);

	return 0;
}
无注释代码:

#include <memory.h>
#include <stdio.h>

#define	MAXN	50001
#define	MOD3(x)	( (x) % 3 )

int		fath[MAXN];
char	rela[MAXN];

int
find(int x) {

	int		fx;

	if ( x == fath[x] ) return x;

	fx = fath[x];
	find(fx);
	rela[x] = MOD3(rela[x] + rela[fx]);

	return fath[x] = find(fx);
}

int
main() {

	int		n, k;
	int		x, y;
	int		fx, fy;
	int		cmd;
	int		i;

	int		fault;

	scanf("%d%d", &n, &k);
	fault = 0;

	for ( i = 1; i <= n; i++ ) fath[i] = i;
	memset(rela, 0, sizeof(0));

	while ( k-- ) {
	
		scanf("%d%d%d", &cmd, &x, &y);
		
		if ( x < 1 || y < 1 || x > n || y > n || ( 2 == cmd && x == y ) ) {
		
			fault++;
			continue;
		}

		cmd--;
		fx = find(x);
		fy = find(y);

		if ( fx != fy ) {
		
			fath[fy] = fx;
			rela[fy] = MOD3(rela[x] - rela[y] + cmd + 3);
		}
		else if ( MOD3(rela[y] - rela[x] + 3) != cmd ) fault++;
	}

	printf("%d\n", fault);

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值