一个好题!
题意是:能否把题中的所有边遍历一遍,而且每条边只走一次
如果可以,要求走过的点的异或值最大
边遍历一遍就是:在图中能否找到一条欧拉路径!
那么,我们首先得判断所有的点是不是连通的(注意,如果有孤立点是合法的!因为,它不与任何其他点有边的关系,也就不需要走到它了)
判断连通,肯定就是并查集了
然后呢,我们知道欧拉路的条件是:奇数点的个数为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;
}