The Best Path
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
题意
p个点q个边,要求遍历每个边且仅经过一次,如果不能则输出impossible 如果能,那么没经过一个点,就要异或这个点的值,问最大结果是多少
解题思路
这是一笔画问题,也就是欧拉回路或通路问题。
判断一个图是否是欧拉回路或通路 有两步
1、是通路
2、欧拉回路没有奇度点,欧拉通路有且仅有2个奇度点
题目没卡数据,不需要判断是不是通路也能过。。。。
如果要判断图是否连通就比较麻烦了,因为,如果有孤立点(无边)应该算合法
由欧拉路性质,奇度点数量为0或2。一个节点被进一次出一次,度减2,产生一次贡献,因此节点u的贡献为 val[i] * ((degree[i]/2)%2),
***degree[i]/2表示经过这个点几次,奇数次相当于经过一次,只异或一次就行,偶数次相当于没异或,等价于异或0***
欧拉回路的起点贡献多一次,欧拉通路的起点和终点贡献也多一次。因此如果是欧拉回路的话枚举一下起点,欧拉通路处理两个奇度点就好了。
代码(没判断图是否通路)
#include<cstdio>
#include<iostream>
#include<cstring>
const int maxs=100010;
using namespace std;
int p,q,degree[maxs],val[maxs],ans;
void mxor()//解决欧拉通路和不进行起点多加1的异或
{
ans=0;
for(int i=1;i<=p;++i)
if(degree[i]>0)
ans^=val[i];
}
int main()
{
int t,i,j,b,c,f,odd[3];
scanf("%d",&t);
while(t--)
{
j=f=0;
memset(degree,0,sizeof(degree));
memset(odd,-1,sizeof(odd));
//处理输入
scanf("%d%d",&p,&q);
for(i=1; i<=p; ++i)
scanf("%d",&val[i]);
while(q > 0)
{
q--;
scanf("%d%d",&b,&c);
degree[b]++;
degree[c]++;
}
//判断奇度点个数
for(i=1; i<=p; i++)
{
if(degree[i] & 1)//统计奇度点的个数
{
odd[j]=i;
j++;
if (j > 2)
{
break;
}
}
//如果是奇度点,贡献度要多加一
if(odd[0]==i||odd[1]==i)
val[i]*=(degree[i]/2+1)%2;
else val[i]*=(degree[i]/2)%2;
}
if(j==0||j==2)
f=1;
else
f=0;
//处理输出
if(f==0)printf("Impossible\n");
else
{
if(j==2)//欧拉通路
{
mxor();
printf("%d\n",ans);
}
else if(j==0)//欧拉回路
{
int maxn=-1;
mxor();
for(i=1;i<=p;++i)//枚举回路起点
{
int now=0;
now=val[i]^ans;//多异或一次起点
if(now>maxn)
maxn=now;
}
printf("%d\n",maxn);
}
}
}
return 0;
}
代码 (判断图是否连通)
#include<cstdio>
#include<iostream>
#include<cstring>
const int maxs=100010;
using namespace std;
int a[maxs],p,q,degree[maxs],val[maxs],ans;
int Find(int x)
{
int tmp = x;
while (a[tmp] != tmp)
{
tmp = a[tmp];
}
int now=x,New;//w表示当前结点,new表示当前结点的父亲节点
while(a[now]!=tmp)
{
New=a[now];
a[now]=tmp;
now=New;
}
return tmp;
}
void mxor()//解决欧拉通路和不进行起点多加1的异或
{
ans=0;
for(int i=1;i<=p;++i)
if(degree[i]>0)
ans^=val[i];
}
int main()
{
int t,i,j,b,c,f,odd[3];
scanf("%d",&t);
while(t--)
{
j=f=0;
memset(a,0,sizeof(a));
memset(degree,0,sizeof(degree));
memset(val,0,sizeof(val));
memset(odd,-1,sizeof(odd));
scanf("%d%d",&p,&q);
for(i=1; i<=p; i++)
{
a[i]=i;
}
for(i=1; i<=p; ++i)
scanf("%d",&val[i]);
while(q > 0)
{
q--;
scanf("%d%d",&b,&c);
degree[b]++;
degree[c]++;
int x = Find(b);
int y = Find(c);
if (x != y)
a[x] = y;
}
for(i=1; i<=p; i++)
{
//判断是否通路
if(a[i]==i&& degree[i]>0)
{
k++;
if(k>1) {f=0;break;}
}
if(degree[i] & 1)//统计奇度点的个数
{
odd[j]=i;
j++;
if (j > 2)
break;
}
if(odd[0]==i||odd[1]==i)
val[i]*=((degree[i]/2+1)%2);
else val[i]*=(degree[i]/2)%2;
}
if(j==0||j==2)
f=1;
else
f=0;
if(f==0)printf("Impossible\n");
else if(j==2)//欧拉通路
{
mxor();
printf("%d\n",ans);
}
else if(f&&j==0)//欧拉回路
{
int maxn=-1;
mxor();
for(i=1;i<=p;++i)//枚举回路起点
{
int now=0;
now=val[i]^ans;//多异或一次起点
if(now>maxn)
maxn=now;
}
printf("%d\n",maxn);
}
}
return 0;
}
探讨一笔画问题中寻找经过每条边恰好一次的路径,并最大化路径上节点值的异或结果。介绍如何判断图的欧拉路径特性,通过算法实现及代码示例。

581

被折叠的 条评论
为什么被折叠?



