食物链

第一种是看的有些博客的解法, 也很好,并且用时和带权并查集差不多。

第二种是带权并查集, 思路是按照每个节点和根节点的距离进行分类,总共有三种,所以% 3 就可以了 。

想当初一个月前看这个题是那么的难,现在看来还挺简单的, 我真的成长了呢~


#include <iostream>
#include <cstring>

using namespace std;

const int N = 50010;

int p[3 * N], n, m, sum;

int find(int x)
{
	int j = x, i = x;

	while (p[j] != -1) j = p[j];

	//cout << j << endl;

	while (p[i] != -1)
	{
		int t = p[i];
		p[i] = j, i = t;
	}
	return j;
}

void un(int a, int b)
{
	int x = find(a), y = find(b);

	if (x != y) p[x] = y;
}


bool same(int a, int b)
{
	if (find(a) == find(b)) return true;

	return false;
}

int main()
{
	cin >> n >> m;

	memset(p, -1, sizeof p);

	while (m--)
	{
		int d, a, b; scanf("%d %d %d", &d, &a, &b);

		if (a > n || b > n)
		{
			sum++; continue;
		}
		if (d == 1)
		{
			if (same(a, b + n) || same(a, b + 2 * n)) sum++;
			else
			{
				un(a, b); un(a + n, b + n); un(a + 2 * n, b + 2 * n);
			}
		}
		else
		{
			if (same(a, b) || same(a, b + 2 * n)) sum++;
			else 
			{
				un(a, b + n); un(a + n, b + 2 * n); un(a + 2 * n, b);
			}
		}
		//cout << m << endl;

	}
	cout << sum << endl;
	return 0;
}

#include <iostream>
#include <cstring>

using namespace std;

const int N = 200010;

int p[N], d[N], m, n, sum;


int find(int x)
{
    if(p[x] == -1) return x;
    else 
    {
        int t = p[x];
        
        p[x] = find(p[x]);
        
        d[x] += d[t];
    }
    return p[x];
}


int main()
{
    cin >> n >> m;
    
    memset(p, -1, sizeof p);
    
    while(m --)
    {
        
        int t, a, b; scanf("%d %d %d", &t, &a, &b);
        
        if(a > n || b > n) 
        {
            
            //cout << a << endl;
            sum ++; continue;
        }
        
        int x = find(a), y = find(b);
        
        if(x != y)
        {
            p[x] = y;
            
            d[x] = (d[b] - d[a] - t + 1);
            
            //cout << d[x] << " " << a << b <<  endl;
        }
        else
        {
            if(((t - 1 + d[a]) % 3 + 3) % 3 != (d[b] % 3 + 3) % 3)sum ++;
        }
        
        
    }
    cout << sum << endl;
    
    
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值