首先看到这个题便想到了泽州学长(%%队爷)讲的最小费用最大流,便拿来他的课件学了一学。
但是在码的过程中便会发现一个问题:最小费用最大流在最短路无法走时便会再另找一条路走,
但是这个题显然硬性规定只能按照最短路走,所以正解就是跑一遍最短路,之后按pre[]建新图
跑最大流即可。
注意:这个题还考察了化点为边的思想,和蜥蜴相似
1 #include2 #define int long long 3 #define AA cout<<"Alita"< 4 #define DD cout<<"Dybala"< 5 #define m(a) memset(a,0,sizeof(a)) 6 using namespace std; 7 const int N=1050,M=2e6+10,INF=1e12; 8 int ans,tot=1,S,T,n,m,flag[N],dis[N],f[N],head[N],to[M],ne[M],w[M],d[M]; 9 vector<int>v[N],g[N],pre[N]; 10 struct point 11 { 12 int x,y; 13 friend bool operator <(point a,point b) 14 { 15 return a.y>b.y; 16 } 17 }; 18 void add(int x,int y,int z) 19 { 20 to[++tot]=y; 21 w[tot]=z; 22 ne[tot]=head[x]; 23 head[x]=tot; 24 } 25 void Plus(int x,int y,int z) 26 { 27 v[x].push_back(y); 28 g[x].push_back(z); 29 } 30 void DJ() 31 { 32 memset(dis,0x7f,sizeof(dis)); 33 memset(flag,0,sizeof(flag)); 34 priority_queue q; 35 point p={S,0}; 36 dis[S]=0; 37 q.push(p); 38 while(q.size()) 39 { 40 point p=q.top(); 41 q.pop(); 42 if(flag[p.x]) continue; 43 flag[p.x]=1; 44 for(int i=0;i ) 45 { 46 int y=v[p.x][i]; 47 if(dis[y]>dis[p.x]+g[p.x][i]) 48 { 49 dis[y]=dis[p.x]+g[p.x][i]; 50 pre[y].clear(); 51 if(p.x!=n) pre[y].push_back(p.x); 52 point b={y,dis[y]}; 53 q.push(b); 54 } 55 else if(dis[y]==dis[p.x]+g[p.x][i]) 56 { 57 if(p.x!=n) pre[y].push_back(p.x); 58 } 59 } 60 } 61 } 62 bool bfs(int s) 63 { 64 memset(d,0,sizeof(d)); 65 queue<int>q; 66 q.push(s); 67 d[s]=1; 68 while(q.size()) 69 { 70 int x=q.front(); 71 q.pop(); 72 for(int i=head[x];i;i=ne[i]) 73 { 74 int y=to[i]; 75 if(!w[i]||d[y]) continue; 76 d[y]=d[x]+1; 77 if(y==S) return true; 78 q.push(y); 79 } 80 } 81 return false; 82 } 83 int dfs(int x,int in) 84 { 85 if(x==S) return in; 86 int out=0; 87 for(int i=head[x];i;i=ne[i]) 88 { 89 int y=to[i]; 90 if(!w[i]||d[y]!=d[x]+1) continue; 91 int tmp=dfs(y,min(in,w[i])); 92 in-=tmp; 93 out+=tmp; 94 w[i]-=tmp; 95 w[i^1]+=tmp; 96 } 97 if(!out) d[x]=0; 98 return out; 99 } 100 signed main() 101 { 102 //freopen("1.in","r",stdin); 103 scanf("%lld%lld",&n,&m); 104 S=1;T=n*2; 105 for(int i=1,x,y,z;i<=m;i++) 106 { 107 scanf("%lld%lld%lld",&x,&y,&z); 108 Plus(x,y,z); 109 Plus(y,x,z); 110 } 111 for(int i=1;i<=n;i++) 112 { 113 scanf("%lld",&f[i]); 114 if(i==1||i==n) continue; 115 add(i,n+i,f[i]); 116 add(n+i,i,0); 117 } 118 DJ(); 119 for(int i=1;i<=n;i++) 120 { 121 for(int j=0;j ) 122 { 123 add(n+i,pre[i][j],INF); 124 add(pre[i][j],n+i,0); 125 } 126 } 127 while(bfs(T)) 128 { 129 ans+=dfs(T,INF); 130 } 131 printf("%lld",ans); 132 return 0; 133 }