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

题意:给出n个点,m条边,每个点都有一个权值,每个边能且只能经过一次,求经过点的亦或值

分析:只显然是一个欧拉图的问题,根据描述有可能是欧拉回路也有可能是偶来通路。我们先判断这个图是否能构成欧拉图,用度数来判断就行,如果度数为奇数的点的个数等于零为欧拉回路,等于二为欧拉通路,否则够不成欧拉图。我们先以欧拉通路跑一遍,求出亦或值,然后如果是欧拉回路就枚举一下起点(回路起点和终点相同)。对于亦或值的计算,如果一个点经过了偶数次,他的亦或值就会被抵消,怎么判断经过多少次呢?用每个点的度数+1除以2得到的就是经过这个点的次数。在枚举起点的时候还有一个地方需要注意,假设第一步计算得到的亦或值是ans,不能随时的更新ans,因为ans只能和其中一个点进行亦或。

代码:
 

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define mod 1000000007
#define lowbit(x) (x&(-x))
#define mem(a,b) memset(a,b,sizeof(a))
#define FRER() freopen("in.txt","r",stdin);
#define FREW() freopen("out.txt","w",stdout);

using namespace std;

typedef pair<int,int> pii;
const int maxn = 100000 + 7 , inf = 0x3f3f3f3f ;
int n,m,T,u,v;
int a[maxn],d[maxn];
int main(){
    //FRER();
    //FREW();
    scanf("%d",&T);
    while(T--){
        mem(d,0);mem(a,0);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            d[u]++;d[v]++;
        }
        int cnt = 0;
        for(int i=1;i<=n;i++){
            if(d[i]&1)cnt++;
        }
        if(cnt!=0&&cnt!=2){
            cout<<"Impossible"<<endl;
            continue;
        }
        int ans = 0;
        for(int i=1;i<=n;i++){
            d[i] =  (d[i]+1)>>1;
            if(d[i]&1)
                ans^=a[i];
        }
        int tmp = ans;
        if(cnt==0){
            for(int i=1;i<=n;i++)
                tmp = max(tmp,ans^a[i]);
            ans = tmp;
        }
        cout<<ans<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/Insist_77/article/details/82019105