HDU 3234 Exclusive-OR Regional的题就是硬啊卧槽

带权并查集,思路很清晰,代码很难看。

对于 I u v ,分以下几种情况不合法。

1.num[u] 已确定 && num[u]  != v 。

2.num[u] 的根已确定,若num[u] == v与根节点有冲突。

若合法,则修改num[u] 且 修改num[u]的根节点的信息。

对于 I u v w   ,分以下几种情况不合法。

1.num[u] ,num[v] 均已确定或均可通过根节点确定 且 num[u]^num[v] != w;

2.若u,v在一个集合内,且num[u] ^ num[root]  ^ num[v] ^num[root] = num[u]^num[v] != w;

若合法,且u,v不在一个集合内,合并u,v所在的集合,若num[root_u]已知,num[root_v]未知(设root_v合并后新集合的根),则更新num[root_v]

对于询问:

首先将确定的数的抑或结果计算出来,然后对于剩下的必须符合可以分成X份,每份中必须有偶数个元素。

因为任意两个同根的元素可以由num[u] ^ num[root]  ^ num[v] ^num[root] = num[u]^num[v] 得出。

否则输出I don‘t know.

有些题解的解法简直炫酷到没朋友,通过虚拟出一个值为零的节点节省了很多代码,可见预先设计出好的思路是有多重要。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <string>
#include <map>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 300

using namespace std;

struct N
{
    int fa,re;
}st[20010];

int num[20010];

int Find(int x,int &R)
{
    int f = x,re = 0,tre = 0,temp,tf;

    while(f != st[f].fa)
    {
        re ^= st[f].re;
        f = st[f].fa;
    }

    R = re;

    while(x != st[x].fa)
    {
        temp = st[x].re;
        tf = st[x].fa;

        st[x].re = re^tre;
        st[x].fa = f;

        tre ^= temp;
        x = tf;
    }

    return x;
}

bool Merge(int u,int v,int w)
{
    int fu,fv,ru,rv;

    fu = Find(u,ru);
    fv = Find(v,rv);

    if(num[fu] != -1)
        num[u] = num[fu]^ru;

    if(num[fv] != -1)
        num[v] = num[fv]^rv;

    if(num[u] != -1 && num[v] != -1)
        return (num[u]^num[v]) == w;

    if(fu == fv)
    {
        return (w^ru) == rv;
    }
    else
    {
        st[fu].fa = fv;
        st[fu].re = w^rv^ru;

        if(num[fv] == -1 && num[fu] != -1)
        {
            num[fv] =  num[fu]^st[fu].re;
        }

    }
    return true;
}

bool mark[20];
int  qu[20];

void JudgeQ(char *s)
{
    int i,j,k = 0;

    for(i = 0;s[i]  < '0' || s[i] > '9'; ++i)
        ;

    for(;!(s[i]  < '0' || s[i] > '9'); ++i)
        ;

    for(;s[i] == ' '; ++i)
        ;

    int anw = 0,temp,x;

    while(s[i] != '\0')
    {
        temp = 0;

        for(;!(s[i]  < '0' || s[i] > '9'); ++i)
        {
            temp += (s[i]-'0');
            temp *= 10;
        }

        temp = temp/10 + 1;

        for(;s[i] == ' '; ++i)
            ;
        qu[k++] = temp;
    }

    for(i = 0;i < k; ++i)
    {
        if(num[qu[i]] != -1)
        {
            anw ^= num[qu[i]];
            continue;
        }
        if(num[Find(qu[i],x)] != -1)
        {
            num[qu[i]] = num[Find(qu[i],x)]^x;
            anw ^= num[qu[i]];
        }
    }

    memset(mark,false,sizeof(mark));

    int ru,rv;

    for(i = 0;i < k; ++i)
    {
        if(mark[i] == false && num[qu[i]] == -1)
        {
            for(j = i+1;j < k; ++j)
            {
                if(mark[j] == false && num[qu[i]] == -1 && Find(qu[i],ru) == Find(qu[j],rv))
                {
                    mark[i] = true,mark[j] = true,anw ^= (ru^rv);
                    break;
                }
            }

            if(mark[i] == false)
            {
                printf("I don't know.\n");
                return;
            }
        }
    }

    printf("%d\n",anw);
}

int Judge(char *s)
{
    int i;

    for(i = 0;s[i]  < '0' || s[i] > '9'; ++i)
        ;

    for(;s[i] == ' '; ++i)
        ;

    int ans = 0;

    while(s[i] != '\0')
    {
        ans++;
        for(;!(s[i]  < '0' || s[i] > '9'); ++i)
            ;
        for(;s[i] == ' '; ++i)
            ;
    }
    return ans;
}

int main()
{
    int i,n,m,icase = 1;

    char s[100],ord[100];

    int u,v,w;

    int ans;
    bool wrong,first;

    while(scanf("%d %d%*c",&n,&m) && (n||m))
    {
        for(i = 1;i <= n; ++i)
            st[i].fa = i,st[i].re = 0,num[i] = -1;

        wrong = false,first = true;
        ans = 0;

        printf("Case %d:\n",icase++);

        while(m--)
        {
            gets(s);
            if(first == false)
                continue;
            if(s[0] == 'I')
            {
                ans++;
                if(Judge(s) == 3)
                {
                    sscanf(s,"%s %d %d %d",ord,&u,&v,&w);

                    u++,v++;

                    if(Merge(u,v,w) == false)
                        wrong = true;
                }
                else
                {
                    sscanf(s,"%s %d %d",ord,&u,&w);

                    u++;

                    if(num[u] == -1 && num[Find(u,v)] == -1)
                    {
                        num[u] = w;
                        num[Find(u,v)] = w^st[u].re;
                    }
                    else if(num[u] == -1)
                    {
                        if((num[Find(u,v)]^st[u].re) != w)
                            wrong = true;
                        else
                            num[u] = w;
                    }
                    else if(num[u] != w)
                        wrong = true;
                }

                if(wrong && first)
                {
                    printf("The first %d facts are conflicting.\n",ans);
                    first = false;
                }
            }
            else
            {
                JudgeQ(s);
            }
        }
        printf("\n");
    }

    return 0;
}

HDU 3234 Exclusive-OR Regional的题就是硬啊卧槽

时间: 2024-11-07 14:15:13

HDU 3234 Exclusive-OR Regional的题就是硬啊卧槽的相关文章

hdu 3234 Exclusive-OR (并查集+异或性质)

Exclusive-OR Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2177    Accepted Submission(s): 603 Problem Description You are not given n non-negative integers X0, X1, ..., Xn-1 less than 220 ,

hdu 1999 不可摸数 水题。

不可摸数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7966    Accepted Submission(s): 2024 Problem Description s(n)是正整数n的真因子之和,即小于n且整除n的因子和.例如s(12)=1+2+3+4+6=16.如果任何数m,s(m)都不等于n,则称n为不可摸数. Input 包

HDU 4085 斯坦纳树模板题

Dig The Wells Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 971    Accepted Submission(s): 416 Problem Description You may all know the famous story "Three monks". Recently they find som

HDU 4280 Island Transport 网络流裸题

非递归版好像被卡掉了,其他2个板子都能过. #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<vector> using namespace std; #define ll int const int MAXN = 100100;//点数的最大值 const int MAXM = 400010;//边数的最大值 const in

HDU 4925 Apple Tree(模拟题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4925 解题报告:给你n*m的土地,现在对每一块土地有两种操作,最多只能在每块土地上进行两种操作,第一种是种苹果树操作,第二种是施肥操作,种苹果树操作可以使得该块地 长出一个苹果,施肥操作可以使得与这块土地相邻的土地的苹果产量变为原来的两倍,问可以得到的最多的苹果数量是多少? 例如一个4*4的土地,用1表示在该土地上做第一种操作,0表示在该土地上做第二种操作,可以得到最多苹果的操作如下: 0 1 0

HDU Senior&#39;s Gun (水题)

题意:给n把枪,m个怪兽,每把枪可消灭1怪兽,并获得能量=枪的攻击力-怪兽的防御力.求如何射杀能获得最多能量?(不必杀光) 思路:用最大攻击力的枪杀防御力最小的怪兽明显可获得最大能量.如果每把枪都去射杀刚好1点能量都拿不到的怪物,那简直等于把枪全丢掉. 1 //#pragma comment(linker,"/STACK:102400000,102400000") 2 #include <iostream> 3 #include <stdio.h> 4 #inc

hdu 4970 Killing Monsters(简单题) 2014多校训练第9场

Killing Monsters                                                                        Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description Kingdom Rush is a popular TD game, in which you should b

HDU 4940 Destroy Transportation system 规律题

答案只有2种情况,所以ans = rand()%2; if(ans)puts("happy") else puts("unhappy"); == 想过无源汇的网络流,还是比较麻烦的,然后没往下想... 设s点集有一些点, 多加一个点一定是y增加比较快_(:зゝ∠)_ 然后设s点集只有一个点 #include <cstdio> #include <map> #include <set> #include <algorithm&

hdu 4119 Isabella&#39;s Message 模拟题

Isabella's Message Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4119 Description Isabella and Steve are very good friends, and they often write letters to each other. They exchange funny experiences, talk ab