有源汇上下界最小流
先求出可行流,然后求出 T->S 的最大流,减一下得出最小流
但是样例
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
Output: 2
My output: -99999999999998
然后我输出 inf+ans 就对了,我设的 inf 是1e14 为啥呢?题目:link
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10,M=1e6+10,inf=1e14;
int n,m,s,t;
int h[N],e[M*2],ne[M*2],w[M*2],idx;
void add(int a,int b,int c){
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
int maxflow,cur[N],d[N];
bool bfs(){
for(int i=0;i<=n+1;i++) d[i]=inf;
queue<int> q;q.push(s);
d[s]=0;cur[s]=h[s];
while(!q.empty()){
int x=q.front();q.pop();
for(int i=h[x];~i;i=ne[i]){
int j=e[i];
if(w[i]>0&&d[j]==inf){
q.push(j);
d[j]=d[x]+1;
cur[j]=h[j];
if(j==t) return 1;
}
}
}
return 0;
}
int dinic(int x,int flow){
if(x==t) return flow;
int res=0,k;
for(int i=cur[x];~i&&flow;i=ne[i]){
cur[x]=i;
int j=e[i];
if(w[i]>0&&d[j]==d[x]+1){
k=dinic(j,min(flow,w[i]));
if(!k) d[j]=inf;
w[i]-=k;w[i^1]+=k;
res+=k;flow-=k;
}
}
return res;
}
int a[N],low[M],S,T;
signed main(){
memset(h,-1,sizeof(h));
scanf("%lld%lld%lld%lld",&n,&m,&S,&T);
int u,v,l,r;s=0,t=n+1;
for(int i=1;i<=m;i++){
scanf("%lld%lld%lld%lld",&u,&v,&l,&r);
low[i]=l;
add(u,v,r-l);add(v,u,0);
a[u]-=l,a[v]+=l;
}
int sum=0;
for(int i=1;i<=n;i++){
if(a[i]>0) sum+=a[i],add(s,i,a[i]),add(i,s,0);
else if(a[i]<0) add(i,t,-a[i]),add(t,i,0);
}
add(T,S,inf);add(S,T,0);
int maxflow=0;
while(bfs()) maxflow+=dinic(s,inf);
if(maxflow<sum){
printf("No Solution");
return 0;
}
maxflow=w[idx];
w[idx]=w[idx-1]=0;
s=T,t=S;
while(bfs()) maxflow-=dinic(s,inf);
printf("%lld",inf+maxflow);
return 0;
}