• 【线性基/神仙题】P4151 [WC2011]最大XOR和路径


    Description

    给定一个无向连通图,边有边权,求一个 (1~sim n) 的路径,最大化边权的异或和。如果一条边经过多次则计算多次。

    Input

    第一行是两个整数 (n,m) 代表点数和边数

    下面 (m) 行每行三个整数描述一条边

    Output

    输出一行一个整数代表答案

    Hint

    (1~leq~n~leq~50000,1~leq~m~leq~100000,1~leq~) 边权 (leq~10^{18})

    Solution

    首先注意到一个结论:对于所有的简单环,环上边权的异或和都可以无代价的获取。原因是可以从一号点出发进入该环绕一圈后原路返回。由于一条路径绕两边对答案的贡献为 (0) ,所以这些简单环的异或和都可以无代价取得。那么现在问题就转化成了寻找一条 (1)(n) 的路径,再异或上一些简单环的异或和,最大化答案。

    我们考虑应该寻找哪一条路径:事实上任选一条路径即可。原因是选择的路径和答案路径一定可以构成一个环,所以异或上该环的权值就可以得到最优解。

    考虑最大化异或和可以使用线性基解决。时间复杂度 (O(m~+~n~log^2d)),其中 (d) 为边权

    Code

    #include <cstdio>
    #include <algorithm>
    #ifdef ONLINE_JUDGE
    #define freopen(a, b, c)
    #define printtime()
    #else
    #include <ctime>
    #define printtime() printf("Times used  = %ld ms
    ", clock())
    #endif
    #define ci const int
    #define cl const long long
    
    typedef long long int ll;
    
    namespace IPT {
    	const int L = 1000000;
    	char buf[L], *front=buf, *end=buf;
    	char GetChar() {
    		if (front == end) {
    			end = buf + fread(front = buf, 1, L, stdin);
    			if (front == end) return -1;
    		}
    		return *(front++);
    	}
    }
    
    template <typename T>
    inline void qr(T &x) {
    	char ch = IPT::GetChar(), lst = ' ';
    	while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
    	while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
    	if (lst == '-') x = -x;
    }
    
    template <typename T>
    inline void ReadDb(T &x) {
    	char ch = IPT::GetChar(), lst = ' ';
    	while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
    	while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
    	if (ch == '.') {
    		ch = IPT::GetChar();
    		double base = 1;
    		while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
    	}
    	if (lst == '-') x = -x;
    }
    
    namespace OPT {
    	char buf[120];
    }
    
    template <typename T>
    inline void qw(T x, const char aft, const bool pt) {
    	if (x < 0) {x = -x, putchar('-');}
    	int top=0;
    	do {OPT::buf[++top] = static_cast<char>(x % 10 + '0');} while (x /= 10);
    	while (top) putchar(OPT::buf[top--]);
    	if (pt) putchar(aft);
    }
    
    const int maxn = 50010;
    const int maxm = 200010;
    const int maxl = 61;
    
    struct Edge {
    	int to;
    	ll v;
    	Edge *nxt;
    };
    Edge edge[maxm], *hd[maxn]; int ecnt;
    inline void cont(ci from, ci to, cl v) {
    	Edge &e = edge[++ecnt];
    	e.to = to; e.nxt = hd[from]; e.v = v; hd[from] = &e;
    }
    
    int n, m;
    ll ans;
    bool vis[maxn];
    ll val[maxn], lb[maxl];
    
    void reading();
    void insert(ll);
    void dfs(ci, cl);
    
    
    int main() {
    	freopen("1.in", "r", stdin);
    	qr(n); qr(m);
    	reading();
    	dfs(1, 0);
    	for (int i = maxl - 1; ~i; --i) {
    		ans = std::max(ans, ans ^ lb[i]);
    	}
    	qw(ans, '
    ', true);
    	printtime();
    	return 0;
    }
    
    void reading() {
    	int a, b; ll c;
    	for (int i = 1; i <= m; ++i) {
    		a = 0; b = 0; c = 0; qr(a); qr(b); qr(c);
    		cont(a, b, c); cont(b, a, c);
    	}
    }
    
    void dfs(ci u, cl tp) {
    	vis[u] = true; val[u] = tp;
    	if (u == n) ans = tp;
    	for (Edge *e = hd[u]; e; e = e->nxt) {
    		int to = e->to;
    		if (!vis[to]) dfs(to, tp ^ e->v);
    		else insert(tp ^ e->v ^ val[to]);
    	}
    }
    
    void insert(ll x) {
    	for (int i = maxl - 1; ~i; --i) if (x & (1ll << i)) {
    		if (lb[i]) {
    			x ^= lb[i];
    		} else {
    			lb[i] = x;
    			for (int j = maxl - 1; j > i; --j) if (lb[j]) {
    				lb[j] ^= x;
    			}
    			for (int j = 0; j < i; ++j) if (lb[j] & (1ll << i)) {
    				lb[i] ^= lb[j];
    			}
    			break;
    		}
    	}
    }
    
  • 相关阅读:
    蓝桥杯_买不到的数目
    蓝桥杯_错误票据
    蓝桥杯_数组操作
    剑指OFFER_把二叉树打印成多行
    C语言学习笔记_结构体的内存对齐
    剑指OFFER_二叉搜索树的第k个节点
    局域网ftp工具,带你去探索局域网ftp工具
    这就是Java代码生成器的制作流程(转载)
    ftp工具 绿色,一款非常棒的绿色 ftp工具
    HDFS+ClickHouse+Spark:从0到1实现一款轻量级大数据分析系统(转载)
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/10305718.html
Copyright © 2020-2023  润新知