【BZOJ2095】【POI2010】Bridge 网络流
题目大意
给你一个无向图,每条边的两个方向的边权可能不同。要求找出一条欧拉回路使得路径上的边权的最大值最小。无解输出"NIE"。
\(2\leq n\leq 1000,1\leq m\leq 2000\)
题解
我们先二分答案\(ans\),把边权大于\(ans\)的边删掉。
现在图中还剩下一些有向边和一些无向边,也就是说这是一个混合图。
混合图的欧拉回路怎么求?
先把无向边定向(方向任意),求出每个点的出度\(d1_i\)和入度\(d2_i\)。如果存在点\(i\)使得\(|d1_i-d2_i|\)为奇数,则无解。因为你怎么反向都不可能把\(d1_i-d2_i\)变成\(0\)。
然后把无向边按定向的反方向在图中连边,容量为\(1\)。对于一个点\(i\),如果\(d1_i>d2_i\),则连边\(i\text{->}T\),容量为\(\frac{d1_i-d2_i}{2}\),否则连边\(S\text{->}i\),容量为\(\frac{d2_i-d1_i}{2}\)。
最后跑一次最大流。如果满流就有解,否则无解。
还要用并查集判一下是不是连通图。
为什么这是对的?每流过一条边就表示把这条边反向。对这个网络求最大流就是调整尽可能多的边。流量平衡就表示一个点的入度和出度相同。
这个图把边定向得到
建图后跑最大流可以得到
把满流边反向后得到
这就是一个欧拉回路了
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
struct list
{
int v[100010];
int w[100010];
int t[100010];
int h[1010];
int n;
void clear()
{
memset(h,0,sizeof h);
n=0;
}
void add(int x,int y,int z)
{
n++;
v[n]=y;
w[n]=z;
t[n]=h[x];
h[x]=n;
}
};
list l;
void add(int x,int y,int z)
{
l.add(x,y,z);
l.add(y,x,0);
}
int d[1010];
int S,T;
int bfs()
{
memset(d,-1,sizeof d);
queue<int> q;
q.push(S);
d[S]=0;
int x,i;
while(!q.empty())
{
x=q.front();
q.pop();
for(i=l.h[x];i;i=l.t[i])
if(l.w[i]&&d[l.v[i]]==-1)
{
d[l.v[i]]=d[x]+1;
if(l.v[i]==T)
return 1;
q.push(l.v[i]);
}
}
return 0;
}
int op(int x)
{
return ((x-1)^1)+1;
}
int dfs(int x,int flow)
{
if(x==T)
return flow;
int c,s=0,i;
for(i=l.h[x];i;i=l.t[i])
if(l.w[i]&&d[l.v[i]]==d[x]+1)
{
c=dfs(l.v[i],min(flow,l.w[i]));
s+=c;
flow-=c;
l.w[i]-=c;
l.w[op(i)]+=c;
if(!flow)
break;
}
return s;
}
int f[1010];
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
int lx[2010],ly[2010],w1[2010],w2[2010];
int d1[2010],d2[2010];
int c[2010];//方向
int n,m;
int abs(int x)
{
return x>0?x:-x;
}
int check(int p)
{
memset(d1,0,sizeof d1);
memset(d2,0,sizeof d2);
int i;
for(i=1;i<=n;i++)
f[i]=i;
for(i=1;i<=m;i++)
{
if(p<w1[i]&&p<w2[i])
return 0;
if(p>=w1[i])
{
c[i]=0;
d1[lx[i]]++;
d2[ly[i]]++;
f[find(lx[i])]=find(ly[i]);
}
else
{
c[i]=1;
d1[ly[i]]++;
d2[lx[i]]++;
f[find(lx[i])]=find(ly[i]);
}
}
for(i=1;i<=n;i++)
{
if(abs(d1[i]-d2[i])&1)
return 0;
if(i>1&&find(i)!=find(i-1))
return 0;
}
l.clear();
S=n+1;
T=n+2;
for(i=1;i<=m;i++)
if(p>=w1[i]&&p>=w2[i])
add(ly[i],lx[i],1);
// else
// add(lx[i],ly[i],1);
int s=0,ans=0;
for(i=1;i<=n;i++)
if(d1[i]>d2[i])
{
add(i,T,(d1[i]-d2[i])/2);
s+=(d1[i]-d2[i])/2;
}
else if(d1[i]<d2[i])
add(S,i,(d2[i]-d1[i])/2);
while(bfs())
ans+=dfs(S,0x7fffffff);
return ans==s;
}
int main()
{
// freopen("bzoj2095.in","r",stdin);
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=m;i++)
scanf("%d%d%d%d",&lx[i],&ly[i],&w1[i],&w2[i]);
int l=1,r=1001;
int mid;
while(l<r)
{
mid=(l+r)>>1;
if(check(mid))
r=mid;
else
l=mid+1;
}
if(l>1000)
printf("NIE\n");
else
printf("%d\n",l);
return 0;
}
【BZOJ2095】【POI2010】Bridge 网络流的更多相关文章
- BZOJ2095 POI2010 Bridges 【二分+混合图欧拉回路】
BZOJ2095 POI2010 Bridges Description YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛 ...
- [BZOJ2095][Poi2010]Bridges 二分+网络流
2095: [Poi2010]Bridges Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1187 Solved: 408[Submit][Sta ...
- 【BZOJ-2095】Bridge 最大流 + 混合图欧拉回路 + 二分
2095: [Poi2010]Bridges Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 604 Solved: 218[Submit][Stat ...
- BZOJ2095 [Poi2010]Bridges
首先二分答案...然后这张图变成了有一些有向边,有一些无向边 然后就是混合图欧拉回路的判断 我们知道如果是有向图,它存在欧拉回路的等价条件是所有点的出度等于入度 对于混合图...先不管有向边,把无向边 ...
- 【BZOJ2095】 Bridge
Time Limit: 1000 ms Memory Limit: 128 MB Description YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个 ...
- BZOJ2095:[POI2010]Bridges(最大流,欧拉图)
Description YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛.现在YYD想骑单车从小岛1 ...
- bzoj2095: [Poi2010]Bridges(二分+混合图求欧拉回路)
传送门 这篇题解讲的真吼->这里 首先我们可以二分一个答案,然后把所有权值小于这个答案的都加入图中 那么问题就转化为一张混合图(既有有向边又有无向边)中是否存在欧拉回路 首先 无向图存在欧拉回路 ...
- [BZOJ2095][Poi2010]Bridges 最大流(混合图欧拉回路)
2095: [Poi2010]Bridges Time Limit: 10 Sec Memory Limit: 259 MB Description YYD为了减肥,他来到了瘦海,这是一个巨大的海, ...
- bzoj千题计划228:bzoj2095: [Poi2010]Bridges
http://www.lydsy.com/JudgeOnline/problem.php?id=2095 二分答案,判断是否存在混合图的欧拉回路 如果只有一个方向的风力<=mid,这条边就是单向 ...
随机推荐
- Python入门-字符串常用方法
Python 字符串 字符串是 Python 中最常用的数据类型.我们可以使用引号('或")来创建字符串. 创建字符串很简单,只要为变量分配一个值即可. var1 = 'Hello Worl ...
- Factors of Factorial AtCoder - 2286 (N的阶乘的因子个数)(数论)
Problem Statement You are given an integer N. Find the number of the positive divisors of N!, modulo ...
- C#跨进程读取listview控件中的数据
http://www.cnblogs.com/Charltsing/p/slv32.html 欢迎交流:QQ564955427 读取标准的32位listview控件中的数据,网上已经有很多代码了.今天 ...
- DOM节点左右移动
闲来没事写了个小demo,原本是回答别人博问的,有人比我更快的给出了链接,想想半途而废也不好,就写完了,写个博文记录一下(效果是按照我自己来的,可能和最早别人问的不太一样,反正无关紧要啦) 直接上co ...
- rem移动端适配方案
一. rem vs em 单位 定义 特点 rem font size of the root element 以根元素字体大小为基准 em font size of the element 以父元素 ...
- react组件传值传方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- PHP中对象是按值传递还是按引用传递?
1.首先,什么是按值传递和按引用传递? 按值传递就是仅仅把值传递过去,相当于传递的是值的拷贝,而按引用传递传递的是内存的地址. 在 PHP5 中,如果按引用传递,就是将 zval 的地址赋给另一个变量 ...
- Oracle undo 表空间不可用
由于某次不小心操作,在切换表空间时没有成功,由于把undo的配置参数 undo_management值设置为MANUAL所以在启动数据库时没有报任何错误,但是给表插入数据时报错了,回滚段不可用的错误. ...
- Jquery ajax传递xml方式在ie8下兼容问题
主要问题就是ie8把xml格式在打开的时候转换成了string,我们只用把其转换回xml就可以了. $.ajax({ type:’GET’, url:’list.php?pagenow=’+count ...
- hadoop第一个例子
Java.io.URL 1.编写java程序 package com.company; import java.io.IOException; import java.io.InputStream; ...