拆点限制流量,最小费用流最大流即为答案。
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN=256<<1; const int M=40005; const int INF=1<<30; struct Edge{ int next,to,f,w; }e[M<<1]; int ecnt=1,head[MAXN]; inline void add(int x,int y,int f,int w){ e[++ecnt].next = head[x]; e[ecnt].to = y; e[ecnt].f = f; e[ecnt].w = w; head[x] = ecnt; } int dis[MAXN],lst[MAXN],inq[MAXN],flow[MAXN]; queue<int> Q; bool spfa(int s,int t){ memset(dis,0x3f,sizeof(dis)); Q.push(s);dis[s]=0;flow[s]=1<<30; while(!Q.empty()){ int top=Q.front();Q.pop();inq[top]=0; for(int i=head[top];i;i=e[i].next){ int v=e[i].to; if(dis[v]<=dis[top]+e[i].w||!e[i].f) continue; dis[v]=dis[top]+e[i].w; flow[v]=min(flow[top],e[i].f); lst[v]=i; if(!inq[v]) Q.push(v),inq[v]=1; } } return dis[t]!=0x3f3f3f3f; } int mxflow,mncost; void update(int s,int t){ int cur=t,mx=flow[t]; while(cur!=s){ int i=lst[cur]; e[i].f-=mx;e[i^1].f+=mx; cur=e[i^1].to; } mxflow+=mx;mncost+=dis[t]; } void EK(int s,int t){ while(spfa(s,t))update(s,t); } int S,T; int n,m; int main(){ n=rd();m=rd(); S=1;T=n; int x,y,w; add(1,1+n,INF,0);add(1+n,1,0,0); add(n,n+n,INF,0);add(n+n,n,0,0); for(int i=2;i<n;i++) add(i,i+n,1,0),add(i+n,i,0,0); for(int i=1;i<=m;i++){ x=rd();y=rd();w=rd(); add(x+n,y,1,w);add(y,x+n,0,-w); } EK(S,T); cout<<mxflow<<" "<<mncost<<endl; return 0; }