The Best Path
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 2179 Accepted Submission(s): 867
Problem Description
Alice is planning her travel route in a beautiful valley. In this valley, there are N lakes, and M rivers linking these lakes. Alice wants to start her trip from one lake, and enjoys the landscape by boat. That means she need to set up a path which go through every river exactly once. In addition, Alice has a specific number (a1,a2,...,an) for each lake. If the path she finds is P0→P1→...→Pt, the lucky number of this trip would be aP0XORaP1XOR...XORaPt. She want to make this number as large as possible. Can you help her?
Input
The first line of input contains an integer t, the number of test cases. t test cases follow.
For each test case, in the first line there are two positive integers N (N≤100000) and M (M≤500000), as described above. The i-th line of the next N lines contains an integer ai(∀i,0≤ai≤10000) representing the number of the i-th lake.
The i-th line of the next M lines contains two integers ui and vi representing the i-th river between the ui-th lake and vi-th lake. It is possible that ui=vi.
Output
For each test cases, output the largest lucky number. If it dose not have any path, output "Impossible".
Sample Input
2
3 2
3
4
5
1 2
2 3
4 3
1
2
3
4
1 2
2 3
2 4
Sample Output
2
Impossible
Source
2016 ACM/ICPC Asia Regional Qingdao Online
Recommend
wange2014
一、原题地址
点我传送
二、大致题意
一个无向图,每个点有权值,选择从某一个点出发,使得一笔画经过所有的路,且使得经过的节点的权值异或运算最大。若存在这种通路则输出最大值,否则输出Impossible。
三、思路
一笔画问题就是关于欧拉图的问题。首先应该判断整张图是否是连通的,这里可以用并查集或者DFS来检查。若图不连通,则肯定不能一笔画完成。其次欧拉图的性质,无向图中所有奇数度数的节点的和必定为0或者2。
1、若奇数度数的节点数为0.那么无论从哪个节点作为节点出发都必然是能够完成一笔画的。且终点必然是起点。那么问题就转为了,讨论每个节点在途中被经历了多少次,很显然应该是(当前节点的度数/2)。并且我们知道异或同一个数偶数次相当于没有效果,那么,我们只需要统计那些途中经历了奇数次的节点就可以了。需要注意的是因为我们可以选择从图中任意的节点出发,而对于这个起点来说,实际上他是会被少计算一次经历的次数,也就是说我们在统计次数时应该给他加回去。所以这里需要枚举每个点可能成为起点的情况,然后更新最值。
2、若奇数度数的节点数为2那么其中一个必然为起点,另一个必然为终点。那么实际的操作就是和1一样。
四、代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<math.h>
#include<cmath>
#include<time.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<algorithm>
#include<numeric>
#include<stack>
const int inf = 0x3f3f3f3f;
#define LL long long
const double EI = 2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427;
const double PI = acos(-1.0);
using namespace std;
const int MAXM = 1e6 + 5;
int father[100005];
int cnt[100005];
int find(int x)
{
if (father[x] == x)
return x;
else
return father[x] = find(father[x]);
}
void Union(int x, int y)
{
int rx, ry;
rx = find(x);
ry = find(y);
father[rx] = ry;
}
typedef struct
{
int v, next, cost;
}Edge;
int T;
int n, m;
int val[100005], inde[100005];
void init()
{
for (int i = 1; i <= 100000; i++)father[i] = i;
memset(inde, 0, sizeof(inde));
}
void read()
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &val[i]);
init();
for (int i = 1; i <= m; i++)
{
int u, v;
scanf("%d %d", &u, &v);
Union(u, v);
inde[u]++, inde[v]++;
}
}
void solve()
{
if (n == 0)
{
printf("Impossible\n");
return;
}
int fa = find(1);
for (int i = 1; i <= n; i++)
{
if (find(i) != fa)
{
printf("Impossible\n");
return;
}
}
int num = 0;
for (int i = 1; i <= n; i++)
{
if (inde[i] & 1)
num++;
if (num > 2)break;
}
if (num > 2 || num == 1)
{
printf("Impossible\n");
return;
}
else if (num == 0)
{
int ans = 0;
for (int i = 1; i <= n; i++)
{
cnt[i] = inde[i] / 2;
if (cnt[i] & 1)
ans ^= val[i];
}
int pu = -inf;
for (int i = 1; i <= n; i++)
{
pu = max(pu, ans^val[i]);
}
printf("%d\n", pu);
}
else if (num == 2)
{
int ans = 0;
for (int i = 1; i <= n; i++)
{
if (inde[i] & 1)
{
cnt[i] = (inde[i] + 1) / 2;
}
else
cnt[i] = inde[i] / 2;
if (cnt[i] & 1)
ans ^= val[i];
}
printf("%d\n", ans);
}
return;
}
int main()
{
scanf("%d", &T);
while (T--)
{
read();
solve();
}
}