目录
显示
题目链接
https://www.luogu.com.cn/problem/P3171
题解
首先跑一遍从 \(s\) 到 \(t\) 的最短路,只留下在最短路上的边。
只需在这张新图上跑最大流即可。
#include <cstring> #include <iostream> #include <string> #include <queue> #define INF 0x3f3f3f3f using namespace std; struct graph { struct edge { int v,w,next; long long c; }e[500005]; struct node { int v,e; }p[2005]; int head[2005],vis[2005]; long long dis[2005]; int n,s,t,cnt=1; void init(int N,int S,int T) { n=N,s=S,t=T; } void addedge(int u,int v,int w,int c) { e[++cnt].v=v; e[cnt].w=w; e[cnt].c=c; e[cnt].next=head[u]; head[u]=cnt; } bool spfa() { queue<int> q; memset(dis,63,sizeof(dis)); dis[s]=0,vis[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i;i=e[i].next) if(e[i].w&&dis[u]+e[i].c<dis[e[i].v]) { dis[e[i].v]=dis[u]+e[i].c; p[e[i].v].v=u; p[e[i].v].e=i; if(!vis[e[i].v]) { vis[e[i].v]=1; q.push(e[i].v); } } } return dis[t]<=1e18; } long long mcmf() { long long maxw=0; while(spfa()) { int minw=INF; for(int i=t;i!=s;i=p[i].v) minw=min(minw,e[p[i].e].w); for(int i=t;i!=s;i=p[i].v) { e[p[i].e].w-=minw; e[p[i].e^1].w+=minw; } maxw+=minw; } return maxw; } }g1,g2; int vis[505],n,m; void build() { queue<int> q; q.push(1),vis[1]=1; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=g1.head[u];i;i=g1.e[i].next) { int v=g1.e[i].v; if(g1.dis[v]==g1.dis[u]+g1.e[i].c) { g2.addedge(u+n,v,INF,g1.e[i].c); g2.addedge(v,u+n,0,-g1.e[i].c); if(!vis[v])q.push(v),vis[v]=1; } } } } int main() { cin>>n>>m; g1.init(n,1,n); g2.init(n,n+1,n); for(int i=1;i<=m;i++) { int u,v,c; cin>>u>>v>>c; g1.addedge(u,v,INF,c); g1.addedge(v,u,INF,c); } g1.spfa(); for(int i=1;i<=n;i++) { int x; cin>>x; g2.addedge(i,i+n,x,0); g2.addedge(i+n,i,0,0); } build(); cout<<g2.mcmf()<<endl; return 0; }