poj 1182--食物链 (并查集)

题目链接:https://vjudge.net/contest/220024#problem/E

题目没大意(中文题,哪里还用得到大意)

在原始的基础上,需要考虑到三者的关系维护,还有就是千万不要用C++的输入输出流读取,因为数据量大,时间上会超限

维护的时候首先要考虑反情况(范围外,吃与被吃的关系),如果不存在反情况的话,那么就可以认为这种情况是正确的,

那接下来的做法就是把正确的情况更新一下,吃,被吃和同类的三个关系同时更新一下;如果存在反情况的话,就把定义储

存反情况的数目更新一下即可, 不废话了,还是看代码吧。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
#define MAX_N 51000


int f[4 * MAX_N];
int n, k;
int d, x, y;

int geft(int x)
{
    while(x != f[x])
        x = f[x];
    return x;
}

void finds(int u, int v)
{
    f[geft(v)] = geft(u);
}
///f[x]储存同类  f[x+n]储存吃x的  f[x+2*n]储存被x吃的

bool pan1(int x,int y)/// 判断x和y是同类是不是真话?
{
    if(x<=0 || x>n || y<=0 || y>n)
        return false;
    if(geft(y) == geft(x+n))
        return false;
    if(geft(y) == geft(x+2*n))
        return false;
    return true;
}

bool pan2(int x,int y)/// 判断x吃y是不是真话?
{
    if(x<=0 || x>n || y<=0 || y>n)
        return false;
    if(geft(x) == geft(y))
        return false;
    if(geft(y) == geft(x+2*n))
        return false;
    return true;
}

int main()
{
    int i, j;
    int ans = 0;
    scanf("%d%d", &n, &k);
    for(i=1;i<=4*n;i++)
        f[i] = i;
    for(i=0; i<k; i++)
    {
        scanf("%d%d%d", &d, &x, &y);
        if(x<=0 || x>n || y<=0 || y>n)
        {
            ans++;
            continue;
        }
        if(d == 1)///判断是不是同类
        {
            if(pan1(x, y))
            {
                finds(x, y);
                finds(x+n, y+n);
                finds(x+2*n, y+2*n);
            }
            else
                ans++;
        }
        else
        {
            if(pan2(x,y))
            {
                finds(x+n, y);
                finds(x, y+2*n);
                finds(y+n,x+2*n);
            }
            else
                ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}
View Code

(说不采用C++的输入输出流,还是在不时间超限的基础上,用上了输出的方式,没办法,挺方便的,就是耗时长了一点)

原文地址:https://www.cnblogs.com/zznu17-091041/p/8732377.html