zoukankan      html  css  js  c++  java
  • 「POI2010」Bridges

    传送门
    Luogu团队题链接

    解题思路

    首先二分答案,然后在所有边权小于二分值的边和所有点组成的图中判欧拉回路。
    由于可能出现混合图,所以要用到网络流。
    把所有无向边钦定一个方向,那么原图就是一个有向图。
    那么存在欧拉回路的充要条件就所有点的入度等于出度且图联通。
    我们考虑把点 (x) 的入度与出度之差记作 (Delta x)
    那么对于所有的定向后的无向边 ((u,v)),连一条从 (u ightarrow v) 的容量为 (1) 的边。
    表示将该条边反向可以使 (Delta u += 2,Delta v -= 2)
    然后考虑对于所有度数差小于 (0) 的点 (x),连一条 (s ightarrow x) 的容量为 (frac{|Delta x|}{2}) 的边。
    表示 (x) 需要操作这么多次,使得 (Delta x) 达到 (0)。小于零的情况同理。
    最后判断是否满流即可。

    细节注意事项

    • 细节有点多,要有耐心

    参考代码

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <cctype>
    #include <cmath>
    #include <ctime>
    #include <queue>
    #define rg register
    using namespace std;
    template < typename T > inline void read(T& s) {
    	s = 0; int f = 0; char c = getchar();
    	while (!isdigit(c)) f |= (c == '-'), c = getchar();
    	while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
    	s = f ? -s : s;
    }
    
    const int _ = 1010;
    const int __ = 5010 * 2 + 1010 * 2;
    const int INF = 2147483647;
    
    int tot = 1, head[_], nxt[__], ver[__], cap[__];
    inline void Add_edge(int u, int v, int d)
    { nxt[++tot] = head[u], head[u] = tot, ver[tot] = v, cap[tot] = d; }
    inline void link(int u, int v, int d) { Add_edge(u, v, d), Add_edge(v, u, 0); }
    
    int n, m, s, t, liu, dgr[_], dep[_];
    struct node{ int a, b, c, d; }g[__];
    
    inline int bfs() {
    	static queue < int > Q;
    	memset(dep, 0, sizeof dep);
    	dep[s] = 1, Q.push(s);
    	while (!Q.empty()) {
    		int u = Q.front(); Q.pop();
    		for (rg int i = head[u]; i; i = nxt[i]) {
    			int v = ver[i];
    			if (dep[v] == 0 && cap[i] > 0)
    				dep[v] = dep[u] + 1, Q.push(v);
    		}
    	}
    	return dep[t] > 0;
    }
    
    inline int dfs(int u, int flow) {
    	if (u == t) return flow;
    	for (rg int i = head[u]; i; i = nxt[i]) {
    		int v = ver[i];
    		if (dep[v] == dep[u] + 1 && cap[i] > 0) {
    			int res = dfs(v, min(flow, cap[i]));
    			if (res) { cap[i] -= res, cap[i ^ 1] += res; return res; }
    		}
    	}
    	return 0;
    }
    
    inline int Dinic() {
    	int res = 0;
    	while (bfs()) while (int d = dfs(s, INF)) res += d;
    	return res;
    }
    
    inline bool check(int mid) {
    	s = 0, t = n + 1;
    	tot = 1, memset(head, 0, sizeof head);
    	for (rg int i = 1; i <= m; ++i) {
    		if (g[i].c > mid) return 0;
    		if (g[i].d <= mid) link(g[i].a, g[i].b, 1);
    	}
    	for (rg int i = 1; i <= n; ++i) {
    		if (dgr[i] < 0) link(s, i, -dgr[i] / 2);
    		if (dgr[i] > 0) link(i, t, dgr[i] / 2);
    	}
    	return Dinic() == liu / 2;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("in.in", "r", stdin);
    #endif
    	read(n), read(m);
    	for (rg int i = 1; i <= m; ++i) {
    		read(g[i].a), read(g[i].b), read(g[i].c), read(g[i].d);
    		if (g[i].c > g[i].d)
    			swap(g[i].a, g[i].b), swap(g[i].c, g[i].d);
    		--dgr[g[i].a], ++dgr[g[i].b];
    	}
    	for (rg int i = 1; i <= n; ++i) {
    		if (dgr[i] % 2 != 0) return puts("NIE"), 0;
    		liu += abs(dgr[i]) / 2;
    	}
    	int l = 1, r = 1000;
    	while (l < r) {
    		int mid = (l + r) >> 1;
    		if (check(mid)) r = mid;
    		else l = mid + 1;
    	}
    	printf("%d
    ", l);
    	return 0;
    }
    

    完结撒花 (qwq)

  • 相关阅读:
    Eclipse安装Hadoop插件
    (转)Ubuntu14.0.4中hadoop2.4.0伪分布模式配置
    Hadoop--DataNode无法启动
    启动与关闭hadoop
    hadoop中执行命令时发生错误
    strings命令
    Deriving data from ElasticSearch Engine
    elasticsearch data importing
    reading words in your computer and changing to female voice, linux festival text2wave saving wav files
    DDNS client on a Linux machine
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/11745810.html
Copyright © 2011-2022 走看看