#117. 有源汇有上下界最小流
Posted -xiangyang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#117. 有源汇有上下界最小流相关的知识,希望对你有一定的参考价值。
题目描述
n nn 个点,m mm 条边,每条边 e ee 有一个流量下界 lower(e) ext{lower}(e)lower(e) 和流量上界 upper(e) ext{upper}(e)upper(e),给定源点 s ss 与汇点 t tt,求源点到汇点的最小流。
输入格式
第一行两个正整数 n nn、m mm、s ss、t tt。
之后的 m mm 行,每行四个整数 s ss、t tt、lower ext{lower}lower、upper ext{upper}upper。
输出格式
如果无解,输出一行 please go home to sleep
。
否则输出最小流。
样例
样例输入
7 12 6 7
6 1 0 2147483647
1 7 0 2147483647
6 2 0 2147483647
2 7 0 2147483647
6 3 0 2147483647
3 7 0 2147483647
6 4 0 2147483647
4 7 0 2147483647
6 5 0 2147483647
5 7 0 2147483647
5 1 1 2147483647
3 4 1 2147483647
样例输出
2
数据范围与提示
1≤n≤50003,1≤m≤125003 1 leq n leq 50003 , 1leq m leq 1250031≤n≤50003,1≤m≤125003
题解:
注意数据范围,开太小会超时
#include <bits/stdc++.h> const long long inf= 0x3f3f3f3f3f3f3f; #define ll long long #define MAXN 500003 using namespace std; int n,m;//点数、边数 int sp,tp;//原点、汇点 inline bool scan_d(int &num) { char in;bool IsN=false; in=getchar(); if(in==EOF) return false; while(in!=‘-‘&&(in<‘0‘||in>‘9‘)) in=getchar(); if(in==‘-‘){ IsN=true;num=0;} else num=in-‘0‘; while(in=getchar(),in>=‘0‘&&in<=‘9‘){ num*=10,num+=in-‘0‘; } if(IsN) num=-num; return true; } struct node { int v,next; ll cap; }mp[MAXN*10]; int pre[MAXN],dis[MAXN],cur[MAXN];//cur为当前弧优化,dis存储分层图中每个点的层数(即到原点的最短距离),pre建邻接表 int cnt=0; void init()//不要忘记初始化 { cnt=0; memset(pre,-1,sizeof(pre)); } void add(int u,int v,ll w)//加边 { mp[cnt].v=v; mp[cnt].cap=w; mp[cnt].next=pre[u]; pre[u]=cnt++; mp[cnt].v=u; mp[cnt].cap=0; mp[cnt].next=pre[v]; pre[v]=cnt++; } bool bfs()//建分层图 { memset(dis,-1,sizeof(dis)); queue<int>q; while(!q.empty()) q.pop(); q.push(sp); dis[sp]=0; int u,v; while(!q.empty()) { u=q.front(); q.pop(); for(int i=pre[u];i!=-1;i=mp[i].next) { v=mp[i].v; if(dis[v]==-1&&mp[i].cap>0) { dis[v]=dis[u]+1; q.push(v); if(v==tp) break; } } } return dis[tp]!=-1; } ll dfs(int u,ll cap)//寻找增广路 { if(u==tp||cap==0) return cap; ll res=0,f; for(int &i=cur[u];i!=-1;i=mp[i].next) { int v=mp[i].v; if(dis[v]==dis[u]+1&&(f=dfs(v,min(cap-res,mp[i].cap)))>0) { mp[i].cap-=f; mp[i^1].cap+=f; res+=f; if(res==cap) return cap; } } if(!res) dis[u]=-1; return res; } ll dinic() { ll ans=0; while(bfs()) { for(int i=0;i<=tp;i++) cur[i]=pre[i]; ans+=dfs(sp,inf); } return ans; } int d[MAXN]; int main() { //freopen("E:\acm1\7.in","r",stdin); int s,t; scanf("%d%d%d%d",&n,&m,&s,&t); init(); int x,y,low,up; for (int i = 0; i <m ; ++i) { scan_d(x);scan_d(y);scan_d(low);scan_d(up); add(x,y,up-low); d[x]-=low; d[y]+=low; } ll sum=0; sp=0;tp=n+1; for (int i = 1; i <=n ; ++i) { if(d[i]>0) { sum+=d[i]; add(sp,i,d[i]); } if(d[i]<0) { add(i,tp,-d[i]); } } ll ans=0; ans+=dinic(); add(t,s,inf); ans+=dinic(); if(ans==sum) { printf("%lld ",mp[cnt-1].cap); } else printf("please go home to sleep "); return 0; } //loj117
以上是关于#117. 有源汇有上下界最小流的主要内容,如果未能解决你的问题,请参考以下文章
HDU 3157 Crazy Circuits (有源汇上下界最小流)