一个好题!

题意是:能否把题中的所有边遍历一遍,而且每条边只走一次

如果可以,要求走过的点的异或值最大


边遍历一遍就是:在图中能否找到一条欧拉路径!

那么,我们首先得判断所有的点是不是连通的(注意,如果有孤立点是合法的!因为,它不与任何其他点有边的关系,也就不需要走到它了)


判断连通,肯定就是并查集了

然后呢,我们知道欧拉路的条件是:奇数点的个数为0或者为2(否则无解)


当奇数点个数为2的时候:

说明起点和终点已经固定了,只可能有一种走法

现在我们来想点的度数和走过的次数的关系

举几个例子就能得到结论

degree【i】=1,需要

degree【i】=2,需要

degree【i】=3,不需要

degree【i】=4,不需要

所以,就是degree【i】%4==0和degree【i】%4==3的时候需要


当奇数点个数为0的时候:

是在奇数点个数为2的情况之下继续分析的

因为起点终点不固定,那么可以任意取

所以,我们要枚举那个点多算一次,来计算回路值

取最优的答案即可


#include<bits/stdc++.h>
using namespace std;

const int maxn=1e5+50;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;

int a[maxn],degree[maxn],fa[maxn];
int vis[maxn];

int getfa(int x){
    if (fa[x]==-1) return x;
    return fa[x]=getfa(fa[x]);
}

int main(){
    //freopen("input.txt","r",stdin);
    int t,ans,temp,n,m,k,c,u,v,x,y;
    scanf("%d",&t);
    while(t--){
        memset(fa,-1,sizeof(fa));
        memset(degree,0,sizeof(degree));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        while(m--){
            scanf("%d%d",&u,&v);
            degree[u]++;
            degree[v]++;
            x=getfa(u);
            y=getfa(v);
            if (x!=y) fa[x]=y;
        }
        for(int i=1;i<=n;i++) vis[getfa(i)]++;
        ans=c=k=0;
        for(int i=1;i<=n;i++){
            if (vis[i]>1) k++;
            if (degree[i]%2) c++;
        }
        if (k>1||(c!=0&&c!=2)){
            puts("Impossible");
            continue;
        }
        for(int i=1;i<=n;i++)
        if (degree[i]%2){
            if ((degree[i]/2+1)%2) ans^=a[i];
        }
        else if (degree[i]/2%2) ans^=a[i];
        if (c==0){
            temp=ans;
            for(int i=1;i<=n;i++)
                if (vis[getfa(i)]>1)
                    ans=max(ans,temp^a[i]);
        }
        printf("%d\n",ans);
    }
    return 0;
}