欧拉路——HDU 5883 (2016 ACM/ICPC Asia Regional Qingdao Online 1006)

来源:互联网 发布:数控机床模拟仿真软件 编辑:程序博客网 时间:2024/06/05 18:08
  • 题目链接:
    http://acm.hdu.edu.cn/showproblem.php?pid=5883

  • 参考链接:
    http://blog.csdn.net/angon823/article/details/52564384

  • 分析:
    给出N个点和M条边,每个点有一个数值。求能不能从某点出发,一次走完所有边,并且计算走过点的数值的最大异或值。

  • 题解:
    首先判断一次欧拉回路,然后还需要判断图是否联通!!!(比赛时候忘记判断联通结果WA飞)。

  • 欧拉路:

    1. 欧拉路是指从图中任意一点开始到图中任意一点结束的路径,并且图中每条边通过且只通过一次。

    2. 欧拉回路是指起始点和终止点相同的欧拉路

    3. 无向连通图存在欧拉路条件:
      所有点度都是偶数,或者恰好有两点度是奇数,则有欧拉路。若有奇数电度,则奇数度点一定为欧拉路的起点和终点,否则任意一点可以为起点。

    4. 有向连通图存在欧拉路的条件
      • 每个点的入度等于出度,则存在欧拉回路(任意点起点)。
      • 除两点外所有点入度等于出度。这两点中一点的出度比入度大1,另一点的出度比入度小1,则存在欧拉路。取 出度大者为起点,取 入度大者为终点。
  • AC代码:

/*************************************************************************    > File Name: test.cpp    > Author: Akira     > Mail: qaq.febr2.qaq@gmail.com  ************************************************************************/#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <cmath>#include <vector>#include <set>#include <list>#include <ctime>typedef long long LL;typedef unsigned long long ULL;typedef long double LD;#define MST(a,b) memset(a,b,sizeof(a))#define CLR(a) MST(a,0)#define Sqr(a) ((a)*(a))using namespace std;#define MaxN 100001#define MaxM 1000005#define INF 0x3f3f3f3f#define bug cout<<88888888<<endl;int N,M;LL A[MaxN];LL in[MaxN];struct Edge{    int u,v;    int next;    int vis;}edge[MaxM];int head[MaxN];int cont;void add(int u, int v){    edge[cont].v = v;    edge[cont].u = u;    edge[cont].vis = 0;    edge[cont].next = head[u];    head[u] = cont++;}void Add(int u, int v)   {    add(u, v);      add(v, u);   }void init()              {    cont = 0;    MST(head,-1);    CLR(in);}int num;int vist[MaxN];void dfs(int x){    num++;    vist[x] = 1;    int p=head[x];    while(p!=-1)    {        int v = edge[p].v;        if(!vist[v])        {            dfs(v);        }        p = edge[p].next;    }}int t;int main(){    scanf("%d", &t);    while(t--)    {        init();        CLR(vist);        num = 0;        scanf("%d%d", &N, &M);        for(int i=1;i<=N;i++)        {            scanf("%lld", &A[i]);        }        int u,v;        for(int i=1;i<=M;i++)        {            scanf("%d%d", &u, &v);            Add(u,v);            in[u]++;            in[v]++;        }        if(M == 0)        {            cout << 0 << endl;            continue;        }        int s = 1,cnt = 0;        for(int i=1;i<=N;i++)        {            if(in[i]&1)            {                if(cnt == 0) s = i;                cnt++;            }           }        if(cnt == 0 || cnt == 2)        {            dfs(s);   //走一遍图,num记录走了多少点            if(num!=N)//判断图是否联通            {                cout << "Impossible\n";                continue;            }            LL Ans = 0;            for(int i=1;i<=N;i++)            {                if(in[i]%2)                {                    Ans ^= (((in[i]/2)+1)%2)*A[i];//(in[i]/2+1)为奇数度点会被走的次数                }                else                {                    Ans ^= ((in[i]/2)%2)*A[i];//(in[i]/2)为偶数度点会被走的次数                }            }            if(cnt == 0)//如果度数全部为偶数,那么最后只要留下最大的A值即可            {                int max = 0;                for(int i=1;i<=N;i++)                {                    if((Ans^A[i])>max)                    {                        max = (Ans^A[i]);                    }                }                Ans = max;            }            cout << Ans << endl;        }        else        {            cout << "Impossible\n";        }    }    //system("pause");}
0 0
原创粉丝点击