zoj 3792 最小割等于最大流 Romantic Value
来源:互联网 发布:淘宝回收卡西欧可靠吗 编辑:程序博客网 时间:2024/05/16 06:19
题意:
可以把残留网络的零流的边设成容量为1,其他设成无穷,再求一次最大流。最后流量一定等于割边边数
另外:
还有一种求割边的办法。
可以把残留网络的零流的边设成容量为1,其他设成无穷,再求一次最大流。最后流量一定等于割边边数
另外:
还有一种求割边的办法。
因为每次我们求出来最大流都是割边的流量,那么,我们可以把原先边的容量×10000+1,那么求出来的最大流/10000不会影响原先的答案,而最大流%10000则是割边的数目
第一种是先求完然后再赋值再求顺便第一次用dinic算法#include<cstdio>#include<iostream>#include<algorithm>#include<queue>#include<cstring>#define INF 0x3f3f3f3fusing namespace std;struct node{ int v,w,next;} edge[500000];int head[5000000],cnt,l[500000],n,m,s,t;void add(int u,int v,int w){ edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].w=0; edge[cnt].next=head[v]; head[v]=cnt++;}int bfs(){ memset(l,-1,sizeof(l)); l[s]=0; queue<int>q; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(l[v]==-1&&edge[i].w) { l[v]=l[u]+1; q.push(v); } } } return l[t]>0;}int dfs(int u,int f){ int a,flow=0; if(u==t) { return f; } for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(l[v]==l[u]+1&&edge[i].w&&(a=dfs(v,min(f,edge[i].w)))) { edge[i].w-=a; edge[i^1].w+=a; flow+=a; f-=a; if(!f) break; } } if(!flow) l[u]=-1; return flow;}int dinic(){ int a,ans=0; while(bfs()) { while(a=dfs(s,INF)) ans+=a; } return ans;}int main(){ int i,j,u,v,w,T,q,p; scanf("%d",&T); while(T--) { scanf("%d %d %d %d",&n,&m,&p,&q); memset(head,-1,sizeof(head)); cnt=0; s=p; t=q; int sum=0; for(i=1;i<=m;i++) { scanf("%d %d %d",&u,&v,&w); add(u,v,w); add(v,u,w); sum+=w; } if(!bfs()) { printf("Inf\n"); continue; } int ans=dinic(); for(int i=0;i<cnt;i+=2) { if(edge[i].w==0) edge[i].w=1; else edge[i].w=INF; edge[i^1].w=0; } int num=0; int a; while(bfs()) { while(a=dfs(s,INF)) num+=a; } printf("%.2lf\n",(double)(sum-ans)/num); } return 0;}下面是*10000+1的算法,自己写了一份老师WA可能是刚开始学习模版运用还不熟悉有些地方还不懂先贴上开学再来改
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<queue>using namespace std;#define INF 0x3f3f3f3f#define dou 10000struct node{ int u, v, w, next;} edge[600000] ;int head[600000], pre[600000], cur[600000];int dis[600000],gap[60000],aug[60000];int s,e,T,cnt,m,n;void add(int u,int v,int w){ edge[cnt].u=u; edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].u=v; edge[cnt].v=u; edge[cnt].w=0; edge[cnt].next=head[v]; head[v]=cnt++;}int SAP(){ int max_flow = 0, v, u = s; int id, mindis; aug[s] = INF; pre[s] = -1; memset(dis, 0, sizeof(dis)); memset(gap, 0, sizeof(gap)); gap[0] = T; for (int i = 0; i <=T; ++i) { // 初始化当前弧为第一条弧 cur[i] = head[i]; } while (dis[s] < T) { bool flag = false; if (u == e) { max_flow += aug[e]; for (v = pre[e]; v != -1; v = pre[v]) // 路径回溯更新残留网络 { id = cur[v]; edge[id].w -= aug[e]; edge[id^1].w += aug[e]; aug[v] -= aug[e]; // 修改可增广量,以后会用到 if (edge[id].w == 0) u = v; // 不回退到源点,仅回退到容量为0的弧的弧尾 } } for (id = cur[u]; id != -1; id = edge[id].next) { // 从当前弧开始查找允许弧 v = edge[id].v; if (edge[id].w > 0 && dis[u] == dis[v] + 1) // 找到允许弧 { flag = true; pre[v] = u; cur[u] = id; aug[v] = min(aug[u], edge[id].w); u = v; break; } } if (flag == false) { if (--gap[dis[u]] == 0) break; // gap优化,层次树出现断层则结束算法 mindis = T; cur[u] = head[u]; for (id = head[u]; id != -1; id = edge[id].next) { v = edge[id].v; if (edge[id].w > 0 && dis[v] < mindis) { mindis = dis[v]; cur[u] = id; // 修改标号的同时修改当前弧 } } dis[u] = mindis + 1; gap[dis[u]]++; if (u != s) u = pre[u]; // 回溯继续寻找允许弧 } } return max_flow;}int main(){ int i,j,u,v,w,t,q,p; scanf("%d",&t); while(t--) { scanf("%d %d %d %d",&n,&m,&p,&q); memset(head,-1,sizeof(head)); cnt=0; s=p; e=q; T=e+1; int all=0; for(i=1; i<=m; i++) { scanf("%d %d %d",&u,&v,&w); all+=w; add(u,v,w*dou+1); add(v,u,w*dou+1); } int cost=SAP(); int bian=cost%dou; cost=all-cost/dou; if(bian==0) { puts("Inf"); continue; } double ans=(double)(cost)/(double)bian; printf("%.2lf\n",ans); } return 0;}下面是*10000+1的正确代码是看了别人的
#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#define init(a) memset(a,0,sizeof(a))const int N = 210;const int maxn = 1000;const int maxm = 5000;#define MIN INT_MIN#define MAX 0x3f3f3f3f#define LL long longusing namespace std;int max(int a,int b){if(a>b)return a; else return b;}int min(int a,int b){if(a<b)return a; else return b;}int n,m;int head[maxn],bnum;int dis[maxn];int num[maxn];int cur[maxn];int pre[maxn];struct node{ int v, cap; int next;}edge[maxm];void add(int u, int v, int cap){ edge[bnum].v=v; edge[bnum].cap = cap; edge[bnum].next = head[u]; head[u]=bnum++; edge[bnum].v=u; edge[bnum].cap=0; edge[bnum].next=head[v]; head[v]=bnum++;}void BFS(int source,int sink){ queue<int>q; while(q.empty()==false) q.pop(); init(num); memset(dis,-1,sizeof(dis)); q.push(sink); dis[sink]=0; num[0]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].v; if(dis[v] == -1) { dis[v] = dis[u] + 1; num[dis[v]]++; q.push(v); } } }}LL ISAP(int source,int sink,int n){ memcpy(cur,head,sizeof(cur)); LL flow=0; int u = pre[source] = source; BFS( source,sink); while( dis[source] < n ) { if(u == sink) { int df = MAX, pos; for(int i = source;i != sink;i = edge[cur[i]].v) { if(df > edge[cur[i]].cap) { df = edge[cur[i]].cap; pos = i; } } for(int i = source;i != sink;i = edge[cur[i]].v) { edge[cur[i]].cap -= df; edge[cur[i]^1].cap += df; } flow += df; u = pos; } int st; for(st = cur[u];st != -1;st = edge[st].next) { if(dis[edge[st].v] + 1 == dis[u] && edge[st].cap) break; } if(st != -1) { cur[u] = st; pre[edge[st].v] = u; u = edge[st].v; } else { if( (--num[dis[u]])==0 ) break; int mind = n; for(int id = head[u];id != -1;id = edge[id].next) { if(mind > dis[edge[id].v] && edge[id].cap != 0) { cur[u] = id; mind = dis[edge[id].v]; } } dis[u] = mind+1; num[dis[u]]++; if(u!=source) u = pre[u]; } } return flow;}void initt(){ memset(head,-1,sizeof(head)); bnum=0;}int main(){ int T,N,M,P,Q; scanf("%d",&T); while(T--) { initt(); int u,v,w,sum = 0; scanf("%d%d%d%d",&N,&M,&P,&Q); for(int i = 1;i<=M;i++) { scanf("%d%d%d",&u,&v,&w); sum += w; add(u,v,w*10000+1); add(v,u,w*10000+1); } LL ans = ISAP(P,Q,N); if(!ans) { puts("Inf"); continue; } int num = ans/10000; int num1 = ans%10000; //printf("ans = %d num = %d num1 = %d",ans,num,num1); printf("%.2lf\n",(double)(sum-num)/num1); } return 0;}
0 0
- zoj 3792 最小割等于最大流 Romantic Value
- zoj 3792 Romantic Value(最小割)
- ZOJ 3792 Romantic Value 最小割
- ZOJ 3792 Romantic Value 最小割
- ZOJ 3792 - Romantic Value (网络流‘最小割)
- zoj3792 Romantic Value 最大流<->最小割
- zoj 3792 Romantic Value(最小割下边数最小)
- zoj3792--Romantic Value(最大流+最小割,求解割边)
- zoj-3792-Romantic Value-最小割+数值转化
- ZOJ 3792 Romantic Value(最小割问题)
- ZOJ 3792 Romantic Value(ISAP && 最小割)
- ZOJ 3792 Romantic Value 最小割+求割边的数量
- ZOJ 3792 Romantic Value(网络流之最小割)(找割边)
- ZOJ 3792 Romantic Value 最小割(最小费用下最小边数)
- ZOJ 3764 - ZOJ Monthly, March 2014 最大流最小割
- zoj 3792 最小割
- ZOJ3792_Romantic Value(网络流/最小割=最大流/找割边)
- 最大流/最小割
- 取消单选按钮选中
- Python模块学习——logging
- 编写自己的异常类
- PHPer 发展之路
- android_01 button
- zoj 3792 最小割等于最大流 Romantic Value
- 关于Struts2实现简单权限拦截功能
- ZOJ-3713
- vimrc 编辑
- 你写的C语言代码在内存里是如何布局的?
- Nginx的location和rewrite配置语法
- mysql 数据库主从数据同步
- nyist oj 171 聪明的kk (动态规划)
- 子页面的Iframe刷新子页面的Iframe