费用流。
裸的拆点最小费用流,一跑就行。
核弹预警,为何wa20多发。build函数一定要返回true。。。。。。
太可怕了
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int maxn = 5000 + 10 ; const int maxm = 200000 + 10; const int inf = 0x3f3f3f3f; int g[maxn],v[maxm],nex[maxm],c[maxm],f[maxm],eid; int n,m; int id[maxn][2],vid,S,T; int dist[maxn],pre[maxn]; bool inque[maxn]; queue<int> q; void addedge(int a,int b,int F,int C) { v[eid]=b; f[eid]=F; c[eid]=C; nex[eid]=g[a]; g[a]=eid++; v[eid]=a; f[eid]=0; c[eid]=-C; nex[eid]=g[b]; g[b]=eid++; } bool build() { memset(id,0,sizeof(id)); if(!(scanf("%d%d",&n,&m) && n && m)) return false; memset(g,-1,sizeof(g)); eid=0; vid=0; for(int i=1;i<=n;i++) { id[i][0]=++vid; id[i][1]=++vid; addedge(id[i][0],id[i][1],1,0); } for(int i=1,u,v,w;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); if(v!=1 && u!=n) addedge(id[u][1],id[v][0],1,w); } S=++vid; T=++vid; addedge(S,id[1][1],2,0); addedge(id[n][0],T,2,0); return true; } bool SPFA() { memset(dist,0x7f,sizeof(dist)); memset(inque,0,sizeof(inque)); memset(pre,0,sizeof(pre)); dist[S]=0; q.push(S); inque[S]=1; int u; while(!q.empty()) { u=q.front(); q.pop(); inque[u]=0; for(int i=g[u];~i;i=nex[i]) if(f[i] && dist[v[i]]>c[i]+dist[u]) { dist[v[i]]=c[i]+dist[u]; pre[v[i]]=i; if(!inque[v[i]]) { q.push(v[i]); inque[v[i]]=1; } } } return dist[T]<inf; } int augment() { int aug=inf,res=0; for(int i=T;i!=S;i=v[pre[i]^1]) aug=min(aug,f[pre[i]]); for(int i=T;i!=S;i=v[pre[i]^1]) { f[pre[i]]-=aug; f[pre[i]^1]+=aug; res+=c[pre[i]]*aug; } return res; } void solve() { int res=0; while(SPFA()) res+=augment(); printf("%d ",res); } int main() { while(build()) solve(); return 0; }