【BZOJ2095】[Poi2010]Bridges

题面

darkbzoj

题解

首先可以想到二分答案,那么我们就是要求我们新图中给所有边定向是否存在欧拉回路。

而有向图存在欧拉回路的充要条件为所有顶点的入度等于出度且该图是连通图,我们考虑在这一点上做文章。

令一个点的入度减出度表示一个点的度数差\(\phi\),首先我们随机定向,假设有两个点\(u\),\(v\),此时我们从\(u\)连一条边向\(v\)。

那么我们每改变一次连边的方向,会使\(\phi_u\)减去\(2\),\(\phi_v\)加上\(2\)。

如果此时存在一点\(x\),\(\phi_x\)为奇数,那么显然无解。

考虑网络流。首先连边\(v\rightarrow u\)流量为\(1\)表示一次转换方向,接着我们对于所有\(\phi>0\)的点\(x\)连边\(S\rightarrow x\),流量为\(\frac {\phi}2\);否则对于所有\(\phi<0\)的点\(x\)连边\(x\rightarrow T\),流量为\(-\frac {\phi}2\)。

直接判断满流即可。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 1005;
struct Graph { int to, cap, next; } e[MAX_N << 5];
int fir[MAX_N], e_cnt;
void clearGraph() { memset(fir, -1, sizeof(fir)); e_cnt = 0; }
void Add_Edge(int u, int v, int c) {
e[e_cnt] = (Graph){v, c, fir[u]}, fir[u] = e_cnt++;
e[e_cnt] = (Graph){u, 0, fir[v]}, fir[v] = e_cnt++;
}
struct Edge { int u, v, a, b; } c[MAX_N << 1];
int N, M, deg[MAX_N];
int level[MAX_N];
bool bfs(int s, int t) {
queue<int> que;
for (int i = 0; i <= N + 1; i++) level[i] = -1;
level[s] = 0, que.push(s);
while (!que.empty()) {
int x = que.front(); que.pop();
for (int i = fir[x]; ~i; i = e[i].next) {
int v = e[i].to; if (!e[i].cap || ~level[v]) continue;
level[v] = level[x] + 1, que.push(v);
}
}
return level[t] != -1;
}
int iter[MAX_N];
int dfs(int x, int t, int f) {
if (x == t) return f;
for (int &i = iter[x]; ~i; i = e[i].next) {
int v = e[i].to;
if (e[i].cap && level[v] > level[x]) {
int d = dfs(v, t, min(f, e[i].cap));
if (d) {
e[i].cap -= d;
e[i ^ 1].cap += d;
return d;
}
}
}
level[x] = -1;
return 0;
}
int dinic(int s, int t) {
int res = 0;
while (bfs(s, t)) {
for (int i = 0; i <= N + 1; i++) iter[i] = fir[i];
int f;
while ((f = dfs(s, t, 1e9))) res += f;
}
return res;
}
bool check(int mid) {
clearGraph();
for (int i = 1; i <= N; i++) deg[i] = 0;
for (int i = 1; i <= M; i++) {
if (c[i].a <= mid) --deg[c[i].u], ++deg[c[i].v];
if (c[i].b <= mid) Add_Edge(c[i].v, c[i].u, 1);
}
for (int i = 1; i <= N; i++) if (deg[i] & 1) return 0;
int cnt = 0, s = 0, t = N + 1;
for (int i = 1; i <= N; i++) {
if (deg[i] > 0) Add_Edge(s, i, deg[i] >> 1), cnt += deg[i] >> 1;
if (deg[i] < 0) Add_Edge(i, t, -deg[i] >> 1);
}
return dinic(s, t) == cnt;
}
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
N = gi(), M = gi();
int l = 1e9, r = 1;
for (int i = 1; i <= M; i++) {
c[i] = (Edge){gi(), gi(), gi(), gi()};
if (c[i].a > c[i].b) swap(c[i].u, c[i].v), swap(c[i].a, c[i].b);
l = min(l, c[i].a), r = max(r, c[i].b);
}
if (!check(r)) return puts("NIE") & 0;
int ans = r;
while (l <= r) {
int mid = (l + r) >> 1;
if (check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%d\n", ans);
return 0;
}

最新文章

  1. [译]学习HTTP协议的请求行
  2. HDU 1698 Just a Hook(线段树 区间替换)
  3. 我的ORM之示例项目
  4. java分布式通信系统(J2EE分布式服务器架构)
  5. kuaisupaixu
  6. c# 贪吃蛇源码
  7. JS正则表达式简单总结
  8. App Store生存指南
  9. RR 和RC 幻读问题
  10. leetcode第一刷_Maximal Rectangle
  11. .NET常见面试题
  12. 开启程序的Visual Styles
  13. Top Open Source Projects to Watch in 2017
  14. Java面试题:Java中怎么样实现多线程
  15. 使用 python 实现π的计算
  16. PADS Logic VX.2.3 修改软件界面语言
  17. zblog如何更改数据库配置以及生效
  18. Python的几个爬虫代码整理(网易云、微信、淘宝、今日头条)
  19. 数据库导入Excel
  20. jquery的DataTable按列排序

热门文章

  1. azure 上传blob到ams(CreateFromBlob)
  2. C#实现电信短信SMGP协议程序源码
  3. HeRaNO&#39;s NOIP CSP Round Day 2 T2 PESTC
  4. Java自学-日期 Date
  5. CORS-跨域资源共享 解决跨域问题
  6. 13、vue如何解决跨域问题
  7. SpringBoot+Security+MyBatis+ES+MQ+Redis+Docker+Vue的电商系统
  8. 第一册: lesson 129。
  9. 基于Chrominum的发行版本Microsoft Edge-Beta
  10. zabbix--基本操作