这题很明显分为两部分,求最大流和最小费用。
目前已知,且能够保证求最大流的 dinic 算法是绝对正确的,但是求醉小费用的时候我总是在 mincost 函数中死循环,已经看了一整天了,找不出问题,求助大佬。
#include<bits/stdc++.h>
#include<unistd.h>
using namespace std;
const int maxn=5005;
const int maxm=50005;
const long long inf=1000000000000000000;
int n,m,s,t;
struct node{
int fr,to,nxt;
long long flow,flow1,cost;
}e[maxm<<1];
int cnt=1,head[maxn],dep[maxn],pre[maxn],vis[maxn],dis[maxn];
int q[maxn],l,r;
void add_edge(int u,int v,int flow,int flow1,int cost){
cnt++;
e[cnt].fr=u;
e[cnt].to=v;
e[cnt].nxt=head[u];
e[cnt].flow=flow;
e[cnt].flow1=flow1;
e[cnt].cost=cost;
head[u]=cnt;
}
bool bfs(){
memset(dep,0,sizeof(dep));
l=1; r=0;
q[++r]=s;
dep[s]=1;
while(l<=r){
int u=q[l];
l++;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(dep[v]==0 && e[i].flow>0){
dep[v]=dep[u]+1;
q[++r]=v;
}
}
}
if(dep[t]==0) return false;
else return true;
}
long long dfs(int u,long long flow){
if(u==t){
return flow;
}
long long tot=0;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(e[i].flow>0 && dep[v]==dep[u]+1){
long long res=dfs(v,min(flow,e[i].flow));
e[i].flow-=res;
e[i^1].flow+=res;
tot+=res;
flow-=res;
if(flow==0) break;
}
}
if(tot==0) dep[u]=0;
return tot;
}
long long dinic(){
long long res=0;
while(bfs()){
res+=dfs(s,inf);
}
return res;
}
bool spfa(){
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
memset(pre,0,sizeof(pre));
dis[s]=0;
vis[s]=true;
l=1; r=0;
q[++r]=s;
while(l<=r){
int u=q[l];
l++;
vis[u]=false;
for(int i=head[u];i;i=e[i].nxt){
if(e[i].cost){
int v=e[i].to;
if(dis[u]+e[i].cost<dis[v]){
dis[v]=dis[u]+e[i].cost;
pre[v]=i;
if(!vis[v]){
q[++r]=v;
vis[v]=true;
}
}
}
}
}
return pre[t]!=0;
}
long long mincost(){
long long res=0;
int i=1;
while(cerr<<spfa()<<endl){
cerr<<"done spfa"<<endl;
long long flow=inf;
for(int i=pre[t];i;i=pre[e[i^1].to]){
flow=min(flow,e[i].flow1);
cerr<<i<<" "<<e[i^1].to<<endl;
sleep(1);
}
cerr<<"get out of the first for"<<endl;
for(int i=pre[t];i;i=pre[e[i^1].to]){
e[i].flow1-=flow;
e[i^1].flow1+=flow;
res+=e[i].cost*flow;
}
cerr<<"get out of the second for"<<endl;
cerr<<"done round "<<i<<endl;
i++;
}
return res;
}
int main(){
cin>>n>>m>>s>>t;
for(int i=1;i<=m;i++){
int u,v,flow,cost;
cin>>u>>v>>flow>>cost;
add_edge(u,v,flow,flow,cost);
add_edge(v,u,0,0,-cost);
}
cout<<dinic()<<" ";
cout<<mincost()<<endl;
return 0;
}