给定一个图,要求选一个点作为起点,然后经过每条边一次,然后把访问过的点异或起来(访问一次就异或一次),然后求最大值。
首先为什么会有最大值这样的分类?就是因为你开始点选择不同,欧拉回路的结果不同,因为是回路,所以你的开始点就会被访问多一次,所以如果是欧拉回路的话,还需要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 "); return; } } if (!(root == 0 || root == 2)) { printf("Impossible "); 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 ", ans); } int main() { #ifdef local freopen("data.txt","r",stdin); #endif // printf("%d ", 1 ^ 3 ^ 4 ^ 5 ^ 6); int t; scanf("%d", &t); while (t--) work(); return 0; }