题目链接:http://acm.uestc.edu.cn/#/problem/show/1219

题目大意是给了一张图,然后要求一个点通过路径回到这个点,使得xor和最大。

这是CCPC南阳站的一道题。当时只读了题目发现并不会。

这是一个典型的xor高斯消元。

需要预先dfs出所有的独立回路。

然后线性组合独立回路的xor和,使得ans最大。

最近做过类似的题目,直接粘代码。

代码:

方法一:线性基(O(63n)

 

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>
#define LL long long

using namespace std;

const int maxN = 50005;
const int maxM = 100005;
int n, m, top;
LL p[maxN], s[maxM];
int vis[maxN];
//链式前向星
struct Edge
{
    int to, next;
    LL val;
}edge[maxM*2];

int head[maxN], cnt;

void addEdge(int u, int v, LL w)
{
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    edge[cnt].val = w;
    head[u] = cnt;
    cnt++;
}

void initEdge()
{
    memset(head, -1, sizeof(head));
    cnt = 0;
}

void dfs(int now, int fa, int t)
{
    vis[now] = t;
    int k;
    for (int i = head[now]; i != -1; i = edge[i].next)
    {
        k = edge[i].to;
        if (k == fa) continue;
        if (vis[k] != -1)
        {
            if (vis[k] <= t)
                s[top++] = p[now]^p[k]^edge[i].val;
        }
        else
        {
            p[k] = p[now]^edge[i].val;
            dfs(k, now, t+1);
        }
    }
}

void input()
{
    initEdge();
    memset(vis, -1, sizeof(vis));
    scanf("%d%d", &n, &m);
    int u, v;
    LL w;
    for (int i = 0; i < m; ++i)
    {
        scanf("%d%d%lld", &u, &v, &w);
        addEdge(u, v, w);
        addEdge(v, u, w);
    }
}

//xor高斯消元求线性基
//时间复杂度O(63n)
int xorGauss(int n)
{
    int row = 0;
    for (int i = 62; i >= 0; i--)
    {
        int j;
        for (j = row; j < n; j++)
            if(s[j]&((LL)1<<i))
                break;
        if (j != n)
        {
            swap(s[row], s[j]);
            for (j = 0; j < n; j++)
            {
                if(j == row) continue;
                if(s[j]&((LL)1<<i))
                    s[j] ^= s[row];
            }
            row++;
        }
    }
    return row;
}

void work()
{
    top = 0;
    p[1] = 0;
    dfs(1, 0, 0);
    int row;
    row = xorGauss(top);
    LL ans = 0;
    for (int i = 0; i < row; ++i)
        ans = max(ans, ans^s[i]);
    printf("%lld\n", ans);
}

int main()
{
    //freopen("test.in", "r", stdin);
    int T;
    scanf("%d", &T);
    for (int times = 0; times < T; ++times)
    {
        printf("Case #%d: ", times+1);
        input();
        work();
    }
    return 0;
}
View Code

相关文章: