简单的费用流
复习一下MCMF算法实现
傻逼建图
对题目翻译:就是把每个点拆成两个点流1费0;
然后出连入流1费边权
天数即:最大流
尽量短:最小费用
#include<bits/stdc++.h>
using namespace std;
const int N=50001;
const int INF=1e9+7;
struct Front_star{
int u,v,w,c,nxt;
}e[N*4];
int cnt=1;
int first[N]={};
void addedge(int u,int v,int w,int c){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].c=c;
e[cnt].nxt=first[u];
first[u]=cnt;
}
void add(int u,int v,int w,int c){
addedge(u,v,w,c);
addedge(v,u,0,-c);
}
int n,m;
int S=0;
int T=500;
int inqueue[N]={};
int dis[N]={};
int pre[N]={};
queue<int> Q;
bool SPFA(){
for(int i=S;i<=T;i++){
dis[i]=INF;
}
dis[S]=0;
Q.push(S);
while(!Q.empty()){
int x=Q.front();
Q.pop();
inqueue[x]=0;
for(int i=first[x];i;i=e[i].nxt){
int v=e[i].v;
if(e[i].w&&dis[v]>dis[x]+e[i].c){
pre[v]=i;
dis[v]=dis[x]+e[i].c;
if(!inqueue[v]){
inqueue[v]=1;
Q.push(v);
}
}
}
}
return dis[T]!=INF;
}
void MCMF(){
int ans=0;
int dat=0;
while(SPFA()){
int s=INF;
for(int i=pre[T];i;i=pre[e[i^1].v]){
s=min(s,e[i].w);
}
for(int i=pre[T];i;i=pre[e[i^1].v]){
e[i].w-=s;
e[i^1].w+=s;
}
ans+=s*dis[T];
dat+=s;
}
cout<<dat<<" ";
cout<<ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
add(u*2+1,v*2,1,c);
}
for(int i=2;i<n;i++){
add(i*2,i*2+1,1,0);
}
add(2,3,INF,0);
add(n*2,n*2+1,INF,0);
add(S,2,INF,0);
add(2*n+1,T,INF,0);
MCMF();
}