题目链接

题意 : 给出一副简单图、要你找出一个回路、使得其路径上边权的异或和最大

分析 :

类似的题有 BZOJ 2115

对于这种异或最长路的题目(走过的边可以重复走)

答案必定是由一条简单路径(链) + 一些基本环构成

这是因为操作是 xor , 具有自反性质 , 可能需要脑补一下

回到这题, 发现答案就是要求找出一个环

那么根据上面那道题目的启发

答案是一个环的情况下, 那么答案环必定也是由其他环来组成

那么只要找出图中所有的基本环, 就可以由这些基本环来线性组合出最大 xor 环了

有一个定理

对于一个图而言、其独立回路的个数为 M - N + 1

独立回路是指任意一个都不能由其他回路构成。

引用一段数学归纳法证明:

“M=N-1时,树,结论成立

设M=K时结论成立,当M=K+1时,任取G中一条边e,G-e中有K-N+1个独立回路,且

任取一个包含e的回路C,显然独立于之前的回路

任意两个包含e的回路C1与C2,C12=C1+C2是G-e的回路,C2不独立

故能且仅能增加一个包含e的独立回路

从而G中恰有(K+1)-N+1个独立回路,证毕”

红色字体引用自 ==> Click here

即一个图最多只有 M + ( N - 1 ) 个独立回路 (即基本环)

而除开独立回路外的图中剩余所有回路都能被这 M - N + 1 个独立回路线性表示

那么由于异或拥有自反性质、即走过两遍的路径不会产生贡献

接下来如果能找出所有的独立回路、这样问题就变成了、给出 N 个数

从中找出异或和最大的组合、这个可以用线性基轻松做到

如何用DFS找出图中所有的独立回路?

首先你考虑生成树, 对于一个图的生成树而言

其基本环(不能由其他环线性表示的环)就是任意两个树上节点 + 非树边构成

那么先 DFS 出生成树, 加上时间戳, 若干当前节点的时间戳大于被遍历到的节点的时间戳

则说明找到一个上面那样子的非树边, 即找到了一个基本环

这样子找出来的环正好有 M - ( N - 1 ) 即所有的边 - 树边这么多

参考自 ==> Click here , Click here

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long

#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)

#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))

#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>

#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;

;

];

;

int n, m;

inline void EdgeInit()
{
    mem(Head, -);
    EdgeCnt = ;
}

inline void AddEdge(int from, int to, LL weight)
{
    int & cnt = EdgeCnt;
    Edge[cnt].v = to;
    Edge[cnt].w = weight;
    Edge[cnt].nxt = Head[from];
    Head[from] = cnt++;
}

struct L_B {
    LL d[], p[];
    int cnt;
    void init() {
        memset(d, , sizeof(d));
        memset(p, , sizeof(p));
        cnt = ;
    }  // 1e18以内的数都适用.
    bool Insert(LL val) {
         ; i >=  ; i --) {
            if (val & (1ll << i)) {
                if (!d[i]) {
                    d[i]=val;
                    break;
                }
                val^=d[i];
            }
        }
        ;
        // 可判断val是否存在于线性基当中.
    }
    LL query_max() {
        LL res = ;
         ; i >=  ; i --) {
            if ((res^d[i]) > res) res ^= d[i];
        }
        return res;
    }
    LL query_min() {  // 应该预先判断能否是0的情况..QAQ
         ; i <=  ; i ++) {
            if (d[i]) return d[i];
        }
        ;
    }
    void rebuild() { // 用于求第k小值.需要先进行独立预处理
         ; i >=  ; i --) {
             ; j >=  ; j --) {
                if (d[i] & (1ll<<j)) d[i] ^= d[j];
            }
        }
         ; i <=  ; i ++) {
            if (d[i]) p[cnt++]=d[i];
        }
    }
    LL kthquery(LL k) { // 注意判断原序列异或出0的情况, 此时应该将k -- 在进行后面的操作.
        LL res = ;
        ;
         ; i >=  ; i --) {
            if (k & (1LL<<i)) res ^= p[i];
        }
        return res;
    }
    void Merge(const L_B &b) { // 把b这个线性基插入到当前这个线性基中.
         ; i >=  ; i --)
            if (b.d[i]) Insert(b.d[i]);
    }
}LB;

int DFN[maxn];
int DFS_Clocks;
LL val[maxn];
VL CycleVal;

inline void DFS(int u, int fa)
{
    DFN[u] = ++DFS_Clocks;
    vis[u] = true;
    for(int i=Head[u]; ~i; i=Edge[i].nxt){
        int v = Edge[i].v;
        if(v == fa) continue;
        if(vis[v] && DFN[v] < DFS_Clocks){///若当前当前点的时间戳大于出度点、则说明找到一条回路
            CycleVal.pb(val[v] ^ val[u] ^ Edge[i].w);
        }else if(!vis[v]){
            val[v] = val[u] ^ Edge[i].w;
            DFS(v, u);
        }
    }
}

int main(void){__stTIME();__IOPUT();

    int nCase;
    sci(nCase);
    ; Case<=nCase; Case++){

        scii(n, m);

        EdgeInit();

        ; i<=m; i++){
            int u, v;
            scii(u, v);
            LL w;
            scl(w);
            AddEdge(u, v, w);
            AddEdge(v, u, w);
        }

        CycleVal.clear();
        ; i<=n; i++)
            vis[i] = false,
            val[i] = 0LL;
        DFS_Clocks = ;
        ; i<=n; i++)
            if(!vis[i])
                DFS(i, -);

        LB.init();

        ; i<(int)CycleVal.size(); i++)
            LB.Insert(CycleVal[i]);

        printf("Case #%d: %lld\n", Case, LB.query_max());
    }

__enTIME();;}

void __stTIME()
{
    #if _TIME
        START = clock();
    #endif
}

void __enTIME()
{
    #if _TIME
        END = clock();
        cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
    #endif
}

void __IOPUT()
{
    #if _INPUT
        freopen("in.txt", "r", stdin);
    #endif
    #if _OUTPUT
        freopen("out.txt", "w", stdout);
    #endif
}

顺带一提, 找出图中所有的简单环, 这个东西是 NP 的, 正是由于 xor

有自反这种美妙的性质, 才能通过基本环+线性基来做这题

求出图中所有环数量的算法, 也是考虑通过生成树的方法 ==> Click here

Codeforces 也有过一道题目, 要求找出环的数量, 标算是状压 ==> Click here

HDU 5544 Ba Gua Zhen ( 2015 CCPC 南阳 C、DFS+时间戳搜独立回路、线性基 )的更多相关文章

  1. HDU 5544 Ba Gua Zhen dfs+高斯消元

    Ba Gua Zhen Problem Description During the Three-Kingdom period, there was a general named Xun Lu wh ...

  2. The 2015 China Collegiate Programming Contest E. Ba Gua Zhen hdu 5544

    Ba Gua Zhen Time Limit: 6000/4000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total ...

  3. 2015南阳CCPC E - Ba Gua Zhen 高斯消元 xor最大

    Ba Gua Zhen Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description During the Three-Kingdom perio ...

  4. Ba Gua Zhen

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5544 学习链接:https://www.cnblogs.com/qscqesze/p/4902518. ...

  5. ACM学习历程—UESTC 1219 Ba Gua Zhen(dfs && 独立回路 && xor高斯消元)

    题目链接:http://acm.uestc.edu.cn/#/problem/show/1219 题目大意是给了一张图,然后要求一个点通过路径回到这个点,使得xor和最大. 这是CCPC南阳站的一道题 ...

  6. hdu 3949 XOR (线性基)

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=3949 题意: 给出n个数,从中任意取几个数字异或,求第k小的异或和 思路: 线性基求第k小异或和,因为题 ...

  7. HDU 4403 A very hard Aoshu problem(dfs爆搜)

    http://acm.hdu.edu.cn/showproblem.php?pid=4403 题意: 给出一串数字,在里面添加一个等号和多个+号,使得等式成立,问有多少种不同的式子. 思路: 数据量比 ...

  8. HDU 3949 XOR 线性基

    http://acm.hdu.edu.cn/showproblem.php?pid=3949 求异或第k小,结论是第k小就是 k二进制的第i位为1就把i位的线性基异或上去. 但是这道题和上一道线性基不 ...

  9. -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】

    [把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...

随机推荐

  1. unittest参数化(paramunittest)

    前言 paramunittest是unittest实现参数化的一个专门的模块,可以传入多组参数,自动生成多个用例前面讲数据驱动的时候,用ddt可以解决多组数据传入,自动生成多个测试用例.本篇继续介绍另 ...

  2. linux学习笔记(1) -- 关于命令的一些操作

    Linux 目录 /:根目录,一般根目录下只存放目录,在Linux下有且只有一个根目录.所有的东西都是从这里开始.当你在终端里输入“/home”,你其实是在告诉电脑,先从/(根目录)开始,再进入到ho ...

  3. 5.Linux常用排查命令

    可以使用一下命令查使用内存最多的10个线程     ps aux | sort -k4nr | head -n 10   可以使用一下命令查使用CPU最多的10个线程     ps aux | sor ...

  4. DFA与动态规划

    1.牛客练习赛45 A 给定字符串, 求字符不相邻的"QAQ"子序列个数. $dp[i][0]$ 只匹配一个'Q'的方案数的前缀和. $dp[i][1]$ 只匹配"QA& ...

  5. Introduction to Deep Learning Algorithms

    Introduction to Deep Learning Algorithms See the following article for a recent survey of deep learn ...

  6. kubernetes 实现redis-statefulset集群

    Kubernetes 通过statefulset部署redis cluster集群 部署redis集群方式的选择 Statefulset Service&depolyment 对于redis, ...

  7. TypeScript入门二:基本数据类型

    浅析基本数据类型 TypeScript类型解析 一.浅析基本数据类型 首先有一个问题TypeScript是一门编译型语言?还是解释性语言?显然已经不能被这两个分类来区分,TypeScript的并不是为 ...

  8. Flutter 34: 图解自定义 View 之 Canvas (一)

    小菜最近在学习自定义 View,刚了解了一下 Paint 画笔的神奇之处,现在学习一下 Canvas 画布的神秘之处.Flutter 提供了众多的绘制方法,小菜接触不深,尽量都尝试一下. Canvas ...

  9. Spring Cloud(四)服务提供者 Eureka + 服务消费者 Feign

    上一篇文章,讲述了如何通过RestTemplate + Ribbon去消费服务,这篇文章主要讲述如何通过Feign去消费服务. Feign简介 Feign是一个声明式的伪Http客户端,它使得写Htt ...

  10. Java检查异常和非检查异常,运行时异常和非运行时异常的区别

    通常,Java的异常(包括Exception和Error)分为检查异常(checked exceptions)和非检查的异常(unchecked exceptions).其中根据Exception异常 ...