【XSY2024】【BZOJ2095】【POI2010】Bridge 网络流
来源:互联网 发布:数据新闻报道方向 编辑:程序博客网 时间:2024/06/05 20:40
题目大意
给你一个无向图,每条边的两个方向的边权可能不同。要求找出一条欧拉回路使得路径上的边权的最大值最小。无解输出”NIE”。
题解
我们先二分答案
现在图中还剩下一些有向边和一些无向边,也就是说这是一个混合图。
混合图的欧拉回路怎么求?
先把无向边定向(方向任意),求出每个点的出度
然后把无向边按定向的反方向在图中连边,容量为
最后跑一次最大流。如果满流就有解,否则无解。
还要用并查集判一下是不是连通图。
为什么这是对的?每流过一条边就表示把这条边反向。对这个网络求最大流就是调整尽可能多的边。流量平衡就表示一个点的入度和出度相同。
这个图把边定向得到
建图后跑最大流可以得到
把满流边反向后得到
这就是一个欧拉回路了
代码
#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;}
阅读全文
0 0
- 【XSY2024】【BZOJ2095】【POI2010】Bridge 网络流
- Bzoj2095:[Poi2010]Bridges:混合图欧拉回路,网络流
- bzoj2095: [Poi2010]Bridges 二分+最大流
- 【BZOJ2095】【最大流】[Poi2010]Bridges 题解
- BZOJ2095 bridge
- bzoj2095【POI2010】Bridges
- bzoj2095 [Poi2010]Bridges
- BZOJ2095: [Poi2010]Bridges
- BZOJ2095[Poi2010] Bridges
- [BZOJ2095][Poi2010]Bridges(二分+最大流+欧拉图)
- 图论欧拉回路初步 & BZOJ2095 POI2010 Bridges
- [BZOJ2095]-[Poi2010]Bridges-二分答案+混合图欧拉回路判定
- bzoj2095 bridges 【网络流判欧拉回路】
- BZOJ 2095 Poi2010 Bridges 二分答案+网络流
- 2095: [Poi2010]Bridges 二分+混合图欧拉回路(网络流)
- bzoj 2095: [Poi2010]Bridges 二分答案+网络流
- bzoj2095 Bridges
- docker bridge 网络
- 构造动态数组
- Opengl学习之模型加载——Assimp
- 我理解的设计模式之观察者模模式
- Android Xutils和Xutils3的基本使用
- C++左值右值和移动语义
- 【XSY2024】【BZOJ2095】【POI2010】Bridge 网络流
- 如何将Spring Boot项目打包部署到外部Tomca
- spring boot 入门学习
- Java IO:File类
- Intent中的四个重要属性——Action、Data、Category、Extras
- Robot Framework使用1-入门
- JVM 内存和GC机制
- 题目1026:又一版 A+B
- html网页什么样的字体最好看,css设置各种中文字体样式代码