最小费用最大流+节点容量
拆点,每个点拆成i和i+n,连一条容量1,费用0的边。
对于i的入边,连到i,出边则从i+n连出。
最后求1+n到n的最小费用最大流。
最大流为天数,最小费用为最短路程。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int inf=1e9;
struct Edge{int from,to,next,v,c;}e[100005];
int head[405],d[405],from[405],cnt=1;
bool inq[405];
void ins(int u,int v,int w,int c){
cnt++;e[cnt].from=u;e[cnt].to=v;
e[cnt].next=head[u];head[u]=cnt;
e[cnt].v=w;e[cnt].c=c;
}
void insert(int u,int v,int w,int c){
ins(u,v,w,c);ins(v,u,0,-c);
}
bool spfa(int s,int t,int &flow,int &cost){
memset(d,0x3f,sizeof(d));
d[s]=0;queue<int>q;q.push(s);
while(!q.empty()){
int u=q.front();q.pop();inq[u]=false;
for(int i=head[u];i;i=e[i].next)
if(e[i].v&&d[e[i].to]>d[u]+e[i].c){
d[e[i].to]=d[u]+e[i].c;
from[e[i].to]=i;
if(!inq[e[i].to]){inq[e[i].to]=true;q.push(e[i].to);}
}
}
if(d[t]>=inf)return false;
int x=inf;
for(int i=from[t];i;i=from[e[i].from])x=min(x,e[i].v);
flow+=x;cost+=d[t]*x;
for(int i=from[t];i;i=from[e[i].from]){
e[i].v-=x;e[i^1].v+=x;
}
return true;
}
void mcmf(int s,int t){
int flow=0,cost=0;
while(spfa(s,t,flow,cost));
printf("%d %d",flow,cost);
}
int main(){
int n,m;scanf("%d%d",&n,&m);
int u,v,w;
for(int i=1;i<=n;i++)insert(i,i+n,1,0);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
insert(u+n,v,1,w);
}
mcmf(1+n,n);
return 0;
}