HDU 5883 2016 ICPC青岛网络赛

本文介绍了一个基于欧拉图的问题,通过寻找一条能够恰好穿过每条边一次的路径来最大化路径上湖泊的幸运数字。文章详细解析了如何利用连通性、节点度数等特性来解决该问题,并给出了完整的AC代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The Best Path

Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 784    Accepted Submission(s): 325


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 P0P1...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 (N100000) and M (M500000), as described above. The i-th line of the next N lines contains an integer ai(i,0ai10000) 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
 
坑爹啊!!!!!!!当时这道题想了我好久好久        想到各种歪的地方    到最后没有一个地方是想对的  都是想多的        日
怎么说呢   一眼看出是欧拉图问题    但是一开始没想起  异或运算的规则   傻傻的把欧拉路径的算法给敲了一直超时
//顺便稍微写一下异或运算的性质好了    1. 两个相同的数异或得  0     2.0与任意一个数异或   则这个数不变    3. 多个数异或与顺序无关
回归正题   关于欧拉图的性质  简单回顾一下
欧拉通路   所有结点连通并且只有两个结点的  度 为奇数
欧拉回路   所有结点连通并且所有结点的  度  为偶数
另外    欧拉通路的起点和终点固定        欧拉回路的起点(也是终点)任意
这样就可以写了    比完之后关注了一下这道题的博客  感觉他们还是有些逻辑漏洞  然而他们还是A了
AC code
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>

using namespace std;
const int maxn=100010;
int n,m;
int val[maxn],root[maxn],degree[maxn],sum[maxn];
bool vis[maxn];

void init()
{
    for(int i=0;i<=n;i++)
    {
        root[i]=i;
        degree[i]=1;//这里把所有节点的度数初始化1   这样就  最后的度数是否为奇数的判断可以省略
        sum[i]=1;//这个图上的连通节点
        vis[i]=true;//初始化设置为true
    }
}

int fin(int x)
{
    return root[x]==x?x:(root[x]=fin(root[x]));
}

int main()
{
    int test,u,v,ru,rv;
    scanf("%d",&test);
    while(test--)
    {
        scanf("%d %d",&n,&m);
        init();
        for(int i=1;i<=n;i++) scanf("%d",val+i);
        while(m--)
        {
            scanf("%d %d",&u,&v);
            degree[u]++;
            degree[v]++;
            ru=fin(u);
            rv=fin(v);
            if(ru!=rv)
            {
                root[ru]=rv;
                sum[rv]+=sum[ru];
            }
        }
        int num=0,ans=0,tmp=0,ri,key=1;
        for(int i=1;i<=n;i++)
            if(degree[i]%2==0) num++;  //因为之前把所有节点的  度  初始化为 1    所以这里的判断改成偶数
        for(int i=1;i<=n;i++)
        {
            ri=fin(i);
            if(ri!=i)
            {
                key=ri;//找到一个连通图   并记录其根节点
                break;
            }
        }
        for(int i=1;i<=n;i++)
            if(fin(i)==i)//对于孤立的节点进行排除
            {
                tmp++;
                vis[i]=false;
            }
        vis[key]=true;
        if(sum[key]+tmp-1!=n||(num!=0&&num!=2))//如果连通图的节点数+孤立点的数目不等于总节点数 那么 必然有另一个连通图 此时必然走不完 
                                               //或者不满足欧拉条件 节点度数为奇数(这里为偶数)的个数
        {
            puts("Impossible");
            continue;
        }
        for(int i=1;i<=n;i++)
        {
            if(!vis[i]) continue;
            if(degree[i]/2%2)//如果经过这个节点有奇数次   则对其进行异或
                ans^=val[i];
        }
        if(num==0)//如果是欧拉回路   那么起点(终点)是任意的   最后再对连通图内的所有节点比较一下
            for(int i=1,tmp=ans;i<=n;i++)  
                if(vis[fin(i)]) ans=max(ans,tmp^val[i]);  
        printf("%d\n",ans);
    }
    return 0;
}

我好菜阿
还要多努力阿








 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值