J - 食物链 POJ - 1182

目录

题目链接

一些话

流程

套路

ac代码


题目链接

J - 食物链

 POJ - 1182 


一些话

这b题目细节太多了,对刚起步的新人非常不友好,写的我想紫砂

写题时得画图理解


流程

带权并查集:食物链

父节点数组,距离数组

find函数:

//由于是将所有节点的指向根节点,而只有最上层的节点是直接指向根节点,所以是自上而下的操作,自下而上的递归。

如果f[x] != x

//储存find(f(x))

int t = find(fx);

//自上而下递归保证d[x]原本储存的是x到f[x]的距离,d[f[x]] 储存的是f[x]到根节点的距离

d[x] += d[f[x]];

f[x] = t;

//由于是自上而下的操作,所以操作写在递归语句后

返回f[x]

//由于是改变f[x] 的值,所以返回值也是f[x]

main函数:

读入n,m

初始化父节点数组

cnt声明

int cnt = 0;

while(m--){

读入op,x,y;

如果x或y>n,假话

else{

fx = find(x),fy = find(y);

如果op是1,

如果x,y在同一个集合(

根节点相同)且x和y到根节点距离差模3不为零,假话

如果x,y不在一个集合,将x集合插到y中

//注意不能直接用else,要else if(fa != fb)确定是因为不在一个集合才没有进入上一条if语句

x根节点的父节点设为y的根节点(即f[x] = x的形式)

x原根节点到新根节点的距离d[x]设为y到根节点距离-x到原根节点距离(根节点变更,所以d[x] + d[fx] 才和d[y]相等,下面同理)

d[fx] = d[y] - d[x];

如果op是2,

如果x,y在同一个集合(根节点相同)且x和y到根节点距离差 - 1 再模3不为零,假话

如果x,y不在一个集合,将x集合插到y中

x根节点的父节点设为y的根节点(即f[x] = x的形式

x原根节点到新根节点的距离d[f[x]设为y到根节点距离-x到原根节点距离

}

输出假话数

return 0;

}


套路

带有维护信息的路径压缩

条件:并查集中要维护信息

int find(int x){
    if(f[x] != x){
        int t = find(f[x];
        d[x] += d[f[x];
        f[x] = t;
    }

    return f[x];
}


ac代码

#include <iostream>
using namespace std;
const int N = 5e4 + 10;
int f[N],d[N];
int find(int x){
	if(f[x] != x){
		
		d[x] += d[f[x]];
		f[x] = find(f[x]);
	}
	return f[x];
}
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n;i++) f[i] = i;
	int cnt = 0;
	while(m--){
		int op,a,b;
		scanf("%d%d%d",&op,&a,&b);
		if(a > n || b > n){
			cnt++;
		}
		else{
			int fa = find(a);
			int fb = find(b);
			if(op == 1){
				if(fa == fb && (d[a] - d[b]) % 3) cnt++;
				else if(fa != fb) {
					f[fa] = fb;
					d[fa] = d[b] - d[a];
				}
			}
			else {
				if(fa == fb && (d[a] - d[b] - 1) % 3) cnt++;
				else if(fa != fb){
					f[fa] = fb;
					d[fa] = d[b] - d[a] + 1;
				}
			}
		}
	}
	printf("%d\n",cnt);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值