HDU - 5883 - The Best Path(欧拉回路/路径)

题目链接
题目大意:给你n个结点的值和m条边,问是否存在一条路径能把所有边都走完且只走一次。如果可以,每个结点每次被经过时就异或上它的值,问得到的最大值是多少。
  很明显是一个关于欧拉路的问题。由于给的图可能存在欧拉路径也可能是回路,所以分类讨论。
  1.首先,用并查集判断一下图的连通性。
  2.检查一下所有点的度数,如果存在2个度为奇数的结点,那就是欧拉路径,如果不存在,那就是欧拉回路,如果度为奇数的结点超过两个,则没有欧拉路。
  3.如果图中存在欧拉路,那么起点和终点被异或的次数就是其度数除以2再加1,其他的结点则是度数的一半。
  4.如果存在欧拉回路,那么起点和终点不是固定的,就有多种走法,而每种走法只有起点多访问了一次。所以说对于其他点来说,被异或的次数还是度数的一半,对于起点来说,是度数的一半加1.这样只要枚举起点取最大值就好了。

//https://www.cnblogs.com/shuitiangong/
#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define endl '\n'
#define rtl rt<<1
#define rtr rt<<1|1
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define zero(a) memset(a, 0, sizeof(a))
#define INF(a) memset(a, 0x3f, sizeof(a))
#define IOS ios::sync_with_stdio(false)
#define _test printf("==================================================\n")
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, ll> P2;
const double pi = acos(-1.0);
const double eps = 1e-8;
const ll MOD =  1000000009;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5+10;
int n, m, p[maxn], deg[maxn], val[maxn];
int find(int root) {
    int son = root, tmp;
    while(root != p[root]) root = p[root];
    while(son != root) {
        tmp = p[son];
        p[son] = root;
        son = tmp;
    }
    return root;
}
void merge(int a, int b) {
    p[find(a)] = find(b);
}
int main(void) {
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        for (int i = 1; i<=n; ++i) {
            p[i] = i;
            deg[i] = 0;
            scanf("%d", &val[i]);
        }
        while(m--) {
            int a, b;
            scanf("%d%d", &a, &b);
            ++deg[a], ++deg[b];
            merge(a, b);
        }
        int root = 0, cnt = 0;
        for (int i = 1; i<=n; ++i) {
            if (p[i]==i) ++root; //并查集检查图的连通性
            if (deg[i]&1) ++cnt; //记录度为奇数的结点个数
        }
        if (root>1 || cnt>2) printf("Impossible\n"); 
        else {
            int ans = 0;
            if (cnt) {
                for (int i = 1; i<=n; ++i)
                    if ((deg[i]+1)>>1&1) ans ^= val[i];
                //对于欧拉路径来说,有2个度为奇数的结点,两个结点的访问次数比度数的一半多1
            }
            else {
                for (int i = 1; i<=n; ++i)
                    if (deg[i]>>1&1) ans ^= val[i];
                for (int i = 1; i<=n; ++i)
                    ans = max(ans, ans^val[i]);
                //对于欧拉回路来说,结点的度数都是偶数,起点的访问次数比度数的一半多1
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}
posted @ 2020-04-06 17:07  shuitiangong  阅读(136)  评论(0编辑  收藏  举报