给定一个图,要求选一个点作为起点,然后经过每条边一次,然后把访问过的点异或起来(访问一次就异或一次),然后求最大值。

 

首先为什么会有最大值这样的分类?就是因为你开始点选择不同,欧拉回路的结果不同,因为是回路,所以你的开始点就会被访问多一次,所以如果是欧拉回路的话,还需要O(n)扫一次,枚举每个点作为起点。

欧拉通路的话,结果是固定的,因为只能从奇数度小的那个点作为起点,奇数度大的那个点作为终点。

 

关于点的访问次数:anstime  = Degree[i] / 2; //如果是奇数的,还要加上一。

因为每两个度就表示:一进一出,度数为2,所以才访问一次。

奇数度的话,剩下的那一个度就是用来出或则进的,

 

然后如果有一个点的度数是0,则可以说明图不联通,

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1e5 + 20;
int a[maxn];
int Degree[maxn];
void init(int n) {
for (int i = 1; i <= n; ++i) {
Degree[i] = 0;
}
}
void work() {
int n, m;
scanf("%d%d", &n, &m);
init(n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for (int i = 1; i <= m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
Degree[u]++;
Degree[v]++;
}
int root = 0;
root = 0;
for (int i = 1; i <= n; ++i) {
root += Degree[i] & 1;
if (Degree[i] == 0) {
printf("Impossible\n");
return;
}
}
if (!(root == 0 || root == 2)) {
printf("Impossible\n");
return;
}
int ans = 0;
int tans = 0;
for (int i = 1; i <= n; ++i) {
int tim = Degree[i] / 2 + (Degree[i] & 1);
tim &= 1;
tans ^= a[i] * tim;
}
if (root == 0) {
for (int i = 1; i <= n; ++i) {
int gg = tans ^ a[i];
ans = max(ans, gg);
}
} else {
ans = tans;
}
printf("%d\n", ans);
}

int main() {
#ifdef local
freopen("data.txt","r",stdin);
#endif
// printf("%d\n", 1 ^ 3 ^ 4 ^ 5 ^ 6);
int t;
scanf("%d", &t);
while (t--) work();
return 0;
}

View Code