首页 > 代码库 > bzoj2115

bzoj2115

线性基+dfs树

我们先搞出dfs树,其实最终路径就是最初的路径和一些环异或。

环最多只有m-n+1,因为一共有m条边,然后有n-1条边在dfs树上,所以还剩m-n+1条边,都可以构成环。

所以dfs搞出环,线性基找最大值就可以了。

技术分享
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, ll> PII;
const int N = 200010;
int n, m, cnt;
vector<PII> G[N];
ll a[N], d[N];
int used[N];
void gauss()
{
    int now = 1;
    for(int i = 62; i >= 0; --i)
    {    
        bool flag = false;
        for(int j = now; j <= cnt; ++j) 
            if(a[j] & (1ll << i)) 
            {
                swap(a[j], a[now]);
                flag = true;
                break;
            }
        if(!flag) continue;
        for(int j = 1; j <= cnt; ++j) if((a[j] & (1ll << i)) && j != now)    
            a[j] ^= a[now];
        ++now;
    }
    --now;
}
void dfs(int u, int last)
{
    used[u] = 1;
    for(int i = 0; i < G[u].size(); ++i)
    {
        PII x = G[u][i];
        int v = x.first;
        ll w = x.second;
        if(v == last) continue;
        if(!used[v]) 
        {    
            d[v] = d[u] ^ w;
            dfs(v, u);
        }
        else a[++cnt] = d[v] ^ d[u] ^ w;
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; ++i)
    {
        int u, v;
        ll w;
        scanf("%d%d%lld", &u, &v, &w);
        G[u].push_back(make_pair(v, w));
        G[v].push_back(make_pair(u, w));
    }
    dfs(1, 0);
    ll ans = d[n];
    gauss();
    for(int i = 1; i <= 62 && i <= cnt; ++i) if((ans ^ a[i]) > ans)
        ans ^= a[i];
    printf("%lld\n", ans);
    return 0;
} 
View Code

 

bzoj2115