zoukankan      html  css  js  c++  java
  • [CF Round #278] Tourists

    给定一个n个点m条边的无向图,求图上的两点的所有的简单路径之间的最小边。
    蓝链
    $ n,m,q leq 100000, w_i leq 10 ^7$

    Solution

    考虑建立用缩点双来建立广义圆方树,然后方点的值是当前点双内最小的点 ,这样就直接维护树上的最小值就可以了。 但如果更新的是根节点。那么他的每个方儿子都会被更新。所以特别处理一下根节点即可。记方点权值为除根节点外的点。特别处理一下即可。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
    #define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
    #define clar(a, b) memset((a), (b), sizeof(a))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define Debug(s) debug("The massage in line %d, Function %s: %s
    ", __LINE__, __FUNCTION__, s)
    typedef long long LL;
    typedef long double LD;
    const int BUF_SIZE = (int)1e6 + 10;
    struct fastIO {
        char buf[BUF_SIZE], buf1[BUF_SIZE];
        int cur, cur1;
        FILE *in, *out;
        fastIO() {
            cur = BUF_SIZE, in = stdin, out = stdout;
    		cur1 = 0;
        }
        inline char getchar() {
            if(cur == BUF_SIZE) fread(buf, BUF_SIZE, 1, in), cur = 0;
            return *(buf + (cur++));
        }
        inline void putchar(char ch) {
            *(buf1 + (cur1++)) = ch;
            if (cur1 == BUF_SIZE) fwrite(buf1, BUF_SIZE, 1, out), cur1 = 0;
        }
        inline int flush() {
            if (cur1 > 0) fwrite(buf1, cur1, 1, out);
            return cur1 = 0;
        }
    }IO;
    #define getchar IO.getchar
    #define putchar IO.putchar
    int read() {
    	char ch = getchar();
    	int x = 0, flag = 1;
    	for(;!isdigit(ch); ch = getchar()) if(ch == '-') flag *= -1;
    	for(;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    	return x * flag;
    }
    void write(int x) {
    	if(x < 0) putchar('-'), x = -x;
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + 48);
    }
    void putString(char s[], char EndChar = '
    ') {
    	rep(i, 0, strlen(s) - 1) putchar(*(s + i));
    	if(~EndChar) putchar(EndChar);
    }
    
    #define Maxn 300009
    struct edge {
    	int to, nxt;
    }g[Maxn << 1], g1[Maxn << 1];
    int n, m, head[Maxn], e, e1, head1[Maxn];
    multiset<int> S[Maxn];
    int val[Maxn];
    int dfn[Maxn], low[Maxn], _clk, cnt_Squ;
    stack <int> s;
    int top[Maxn], dep[Maxn], size[Maxn], son[Maxn];
    int fa[Maxn], efn[Maxn], _index;
    namespace INIT {
    	void add(int u, int v) {
    		g[++e] = (edge){v, head[u]}, head[u] = e;
    	}
    	void add1(int u, int v) {
    		g1[++e1] = (edge){v, head1[u]}, head1[u] = e1;
    	}
    	void tarjan(int u, int fa) {
    		dfn[u] = low[u] = ++_clk;
    		s.push(u);
    		for(int i = head[u]; ~i; i = g[i].nxt) {
    			int v = g[i].to;
    			if(v != fa) 
    				if(!dfn[v]) {
    					tarjan(v, u);
    					low[u] = min(low[u], low[v]);
    					if(low[v] >= dfn[u]) {
    						add1(n + (++cnt_Squ), u), add1(u, n + cnt_Squ);
    						int a;
    						do {
    							a = s.top(); s.pop();
    							add1(n + cnt_Squ, a), add1(a, n + cnt_Squ);
    						}while(a != v);
    					}
    				}else low[u] = min(low[u], dfn[v]);
    		}
    	}
    	void dfs_init(int u, int f) {
    		size[u] = 1;
    		dep[u] = dep[f] + 1, fa[u] = f;
    		for(int i = head1[u]; ~i; i = g1[i].nxt) {
    			int v = g1[i].to;
    			if(v != f) {
    				dfs_init(v, u);
    				size[u] += size[v];
    				if(son[u] == -1 || size[son[u]] < size[v]) v = son[u];
    			}
    		}
    	}
    	void dfs_link(int u, int _top) {
    		top[u] = _top;
    		dfn[u] = ++_index, efn[_index] = u;
    		if(~son[u]) dfs_link(son[u], _top);
    		for(int i = head1[u]; ~i; i = g1[i].nxt) {
    			int v = g1[i].to;
    			if(v ^ fa[u] && v ^ son[u]) dfs_link(v, v);
    		}
    	}
    	void Main() {
    		clar(head, -1);
    		clar(head1, -1);
    		n = read(), m = read();
    		rep(i, 1, n) val[i] = read();
    		rep(i, 1, m) {
    			int u = read(), v = read();
    			add(u, v), add(v, u);
    		}
    		tarjan(1, 0);
    		clar(dfn, 0), _clk = 0;
    		clar(son, -1);
    		dfs_init(1, 0);
    		dfs_link(1, 1);
    		rep(i, 2, n) S[fa[i] - n].insert(val[i]);
    	}
    }
    namespace SGMT_tree {
    	int tree[Maxn << 2];
    #define lc(x) ((x) << 1)
    #define rc(x) ((x) << 1 | 1)
    #define ls rt << 1, l, mid
    #define rs rt << 1 | 1, mid + 1, r
    	void pushup(int root) {
    		tree[root] = min(tree[lc(root)], tree[rc(root)]);
    	}
    	void build(int rt, int l, int r) {
    		if(l == r) {
    			tree[rt] = (efn[l] <= n) ? (val[efn[l]]) : (*S[efn[l] - n].begin());
    			return ;
    		}
    		int mid = (l + r) >> 1;
    		build(ls), build(rs);
    		pushup(rt);
    	}
    	void modify(int rt, int l, int r, int pos) {
    		if(l == r) {
    			tree[rt] = (efn[l] <= n) ? (val[efn[l]]) : (*S[efn[l] - n].begin());
    			return;
    		}
    		int mid = (l + r) >> 1;
    		(pos <= mid) ? modify(ls, pos) : modify(rs, pos);
    		pushup(rt);
    	}
    	int query(int rt, int l, int r, int x, int y) {
    		if(x <= l && r <= y) return tree[rt];
    		int mid = (l + r) >> 1;
    		if(mid >= y) return query(ls, x, y);
    		if(mid + 1 <= x) return query(rs, x, y);
    		return min(query(ls, x, y), query(rs, x, y));
    	}
    #undef lc
    #undef rc
    #undef ls
    #undef rs
    }
    namespace SOLVE {
    	void Main() {
    		int amt = cnt_Squ + n;
    		SGMT_tree :: build(1, 1, amt);
    		rep(i, 1, read()) {
    			char s = getchar();
    			int x = read(), y = read();
    			if(s == 'C') {
    				if(x > 1) {
    					S[fa[x] - n].erase(S[fa[x] - n].lower_bound(val[x]));
    					S[fa[x] - n].insert(y);
    					SGMT_tree :: modify(1, 1, amt, dfn[fa[x]]);
    				}
    				val[x] = y;
    				SGMT_tree :: modify(1, 1, amt, dfn[x]);
    			}
    			if(s == 'Q') {
    				int Tmp = x, res = INT_MAX;
    				while(top[x] != top[y]) {
    					if(dep[top[x]] < dep[top[y]]) swap(x, y);
    					res = min(res, SGMT_tree :: query(1, 1, amt, dfn[top[x]], dfn[x]));
    					x = fa[top[x]];
    				}
    				if(dep[x] < dep[y]) swap(x, y);
    				res = min(res, SGMT_tree :: query(1, 1, amt, dfn[x], dfn[y]));
    				if(x > n) res = min(res, val[fa[x]]);
    				assert(res != INT_MAX);
    				write(val[Tmp] - res), putchar('
    ');
    			}
    		}
    	}
    }
    int main() {
    	INIT :: Main();
    	SOLVE :: Main();
    #ifdef Qrsikno
    	debug("
    Running time: %.3lf(s)
    ", clock() * 1.0 / CLOCKS_PER_SEC);
    #endif
    	return IO.flush();
    }
    
  • 相关阅读:
    周末班:Python基础之面向对象基础
    二分查找
    各种推导式合集
    周末班:Python基础之函数进阶
    Python基础之迭代器和生成器
    Django中的信号
    周末班:Python基础之并发编程
    周末班:Python基础之网络编程
    Python基础之面对对象进阶
    Python基础之协程
  • 原文地址:https://www.cnblogs.com/qrsikno/p/9813679.html
Copyright © 2011-2022 走看看