hdu 5883 The Best Path 欧拉路径 & 欧拉回路 并查集

来源:互联网 发布:淘宝代收驿站 编辑:程序博客网 时间:2024/06/10 08:59

题意:给出一个无向图,问是否存在欧拉路(一笔画),问经过最大的顶点异或和


思路:这题完全是考察欧拉路的性质,所以先来回顾下欧拉路的性质

对于一个图是否存在欧拉路,首先要判断它的连通性,判断连通性可以用并查集或者bfs,dfs,这道题用了并查集


对于无向图

存在欧拉路径的充要条件是度数为奇数的点的个数有且仅有两个,并且必须从其中一个奇点出发,另一个奇点结束

存在欧拉回路的充要条件是不存在度数为奇数的点,并且从任意点出发,最终一定会回到该点

对于有向图

存在欧拉路径的充要条件是有两个点的入度不等于出度,而且必须是其中一个点的出度恰好比入度大一(此点当做起点),另个一的入度比出度大一(当做终点)

存在欧拉路径的充要条件是所有点的入度等于出度


对于这道题是一个无向图,那么判断无向图的充要条件即可,可能是欧拉路径,也可能是欧拉回路。

细节看代码



#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 100005;struct edge{    int u, v, next;} e[5000005];int head[maxn], cnt;void init(){    cnt = 0;    memset(head, -1, sizeof(head));}void addedge(int u, int v){    e[cnt].u = u, e[cnt].v = v, e[cnt].next = head[u], head[u] = cnt++;}int p[maxn], a[maxn];int degree[maxn];//每个顶点的度数int Find(int x){    return x == p[x] ? x : p[x] = Find(p[x]);}void solve(int n){    int res = 0;    for(int i = 1; i <= n; i++)    {        if(degree[i] & 1)            res++;        if(res >= 3) break;    }    if(res == 0)//欧拉回路    {        int ans1 = 0, ans2;        for(int i = 1; i <= n; i++)            if((degree[i] / 2) & 1)//中间顶点的度数/2是个奇数,表明经过这个点奇数次,而异或自己只有奇数次才有效                ans1 ^= a[i];        ans2 = ans1;        for(int i = 1; i <= n; i++)//从任意一个点出发的得到的最大值            if((degree[i] / 2) & 1)                ans2 = max(ans2, ans1 ^ a[i]);        printf("%d\n", ans2);    }    else if(res == 2)//欧拉路径    {        int ans = 0;        for(int i = 1; i <= n; i++)        {            if(degree[i] & 1) //起点和终点必然奉献一次            {                ans ^= a[i];                continue;            }            if((degree[i] / 2) & 1)//中间顶点的度数/2是个奇数,表明经过这个点奇数次,而异或自己只有奇数次才有效                ans ^= a[i];        }        printf("%d\n", ans);    }    else //不存在欧拉路        puts("Impossible");}int main(){    int t, n, m;    scanf("%d", &t);    while(t--)    {        init();        memset(degree, 0, sizeof(degree));        scanf("%d%d", &n, &m);        for(int  i = 1; i <= n; i++)        {            p[i] = i;            scanf("%d", &a[i]);        }        for(int i = 0; i < m; i++)        {            int u, v;            scanf("%d%d", &u, &v);            addedge(u, v);            addedge(v, u);            degree[u]++, degree[v]++;            int fx = Find(u), fy = Find(v);            if(fx != fy)                p[fx] = fy;        }        int res = Find(1);        bool flag = false;        for(int i = 1; i <= n; i++)        {            if(res != Find(i))            {                flag = true;                break;            }        }        if(flag)//这个图不连通        {            puts("Impossible");            continue;        }        solve(n);    }    return 0;}


0 0
原创粉丝点击