题解:
拆点费用流
然后输出cost、flow
代码:
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=100005; int fi[N],n,t,cas,m,x,y,z,f[N],ne[N],num,zz[N],fl[N],gp[N],dist[N],pre[N],sl[N]; void jb(int x,int y,int z,int s) { ne[num]=fi[x]; fi[x]=num; zz[num]=y; sl[num]=z; fl[num++]=s; ne[num]=fi[y]; fi[y]=num; zz[num]=x; sl[num]=0; fl[num++]=-s; } int spfa() { memset(dist,0x3f,sizeof dist); memset(pre,-1,sizeof pre); memset(gp,0,sizeof gp); memset(f,0,sizeof f); queue<int > Q; Q.push(1); dist[1]=0; while (!Q.empty()) { int now=Q.front(); Q.pop(); f[now]=0; for (int i=fi[now];i!=-1;i=ne[i]) if (sl[i]>0) { int t=zz[i]; if (dist[t]>dist[now]+fl[i]) { dist[t]=dist[now]+fl[i]; pre[t]=now; gp[t]=i; if (!f[t]) { f[t]=1; Q.push(t); } } } } if (pre[n]==-1)return 1; return 0; } void Max_flow() { int cost=0,flow=0; while (!spfa()) { int f=1e9; for (int i=n;i>1;i=pre[i]) f=min(f,sl[gp[i]]); cost+=f; flow+=dist[n]*f; for (int i=n;i>1;i=pre[i]) { sl[gp[i]]-=f; sl[gp[i]^1]+=f; } } printf("%d %d\n",cost,flow); } int main() { memset(fi,-1,sizeof fi); scanf("%d%d",&n,&m); while (m--) { scanf("%d%d%d",&x,&y,&z); jb(x+n,y,1,z); } for (int i=2;i<n;i++)jb(i,i+n,1,0); jb(1,1+n,1e9,0); jb(n,n+n,1e9,0); n=n+n; Max_flow(); }