跑出最短路图,然后把结点拆点跑最大流。
#include<cstdio> #include<queue> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define M 100001 #define INF 2147483647 #define N 501 typedef long long ll; namespace Net { int v[M<<1],next[M<<1],first[N<<1],en,cap[M<<1]; queue<int>q; void AddEdge(int U,int V,int Cap) { v[en]=V; cap[en]=Cap; next[en]=first[U]; first[U]=en++; v[en]=U; next[en]=first[V]; first[V]=en++; } int S,T,n; int d[N<<1],cur[N<<1]; int bfs() { memset(d,-1,sizeof(int)*(n+1)); d[S]=0; q.push(S); while(!q.empty()) { int U=q.front(); q.pop(); for(int i=first[U];i!=-1;i=next[i]) if(cap[i]&&d[v[i]]==-1) { d[v[i]]=d[U]+1; q.push(v[i]); } } return d[T]!=-1; } int dfs(int U,int a) { if(U==T||(!a)) return a; int f,Flow=0; for(int &i=cur[U];i!=-1;i=next[i]) if(d[v[i]]==d[U]+1&&(f=dfs(v[i],min(a,cap[i])))) { cap[i]-=f; cap[i^1]+=f; Flow+=f; a-=f; if(!a) break; } if(!Flow) d[U]=-1; return Flow; } ll MaxFlow() { ll Flow=0; int tmp; while(bfs()) { memcpy(cur,first,sizeof(int)*(n+1)); while(tmp=dfs(S,INF)) Flow+=(ll)tmp; } return Flow; } }; namespace SP { int n,m; queue<int>q; int v[M<<1],w[M<<1],next[M<<1],first[N],en; void AddEdge(int U,int V,int W) { v[++en]=V; w[en]=W; next[en]=first[U]; first[U]=en; } ll d[N]; bool inq[N]; void spfa(int S) { for(int i=1;i<=n;++i) d[i]=INF; d[S]=0; q.push(S); inq[S]=1; while(!q.empty()) { int U=q.front(); for(int i=first[U];i;i=next[i]) if(d[U]+(ll)w[i]<d[v[i]]) { d[v[i]]=d[U]+(ll)w[i]; if(!inq[v[i]]) { inq[v[i]]=1; q.push(v[i]); } } q.pop(); inq[U]=0; } } }; int Map(int x,bool op) { if(x==Net::S||x==Net::T) return x; return ((!op)?((x<<1)-2):((x<<1)-1)); } int main() { int x,y,z; scanf("%d%d",&SP::n,&SP::m); for(int i=1;i<=SP::m;++i) { scanf("%d%d%d",&x,&y,&z); SP::AddEdge(x,y,z); SP::AddEdge(y,x,z); } SP::spfa(1); Net::S=1; Net::T=2*SP::n-2; Net::n=2*SP::n-2; memset(Net::first,-1,sizeof(int)*(Net::n+1)); for(int i=1;i<=SP::en;i+=2) { if(SP::d[SP::v[i+1]]+(ll)SP::w[i]==SP::d[SP::v[i]]) Net::AddEdge(Map(SP::v[i+1],1),Map(SP::v[i],0),INF); if(SP::d[SP::v[i]]+(ll)SP::w[i]==SP::d[SP::v[i+1]]) Net::AddEdge(Map(SP::v[i],1),Map(SP::v[i+1],0),INF); } scanf("%d",&x); for(int i=2;i<SP::n;++i) { scanf("%d",&x); Net::AddEdge(Map(i,0),Map(i,1),x); } scanf("%d",&x); cout<<Net::MaxFlow()<<endl; return 0; }