Surface: A non-weighted connected graph, Points n+1 (label 0...N), the number of sides m, there are now K individuals at point No. 0, the request to destroy the 1,2,3....N point in turn. If at least one person passes a point x, the point x is thought to be destroyed. Only points that are smaller than x are destroyed to pass through the X. K individuals can split up. The destroyed point can be passed after it has been destroyed. The minimum value of the sum of the path length passed by the K-person is obtained under the precondition of satisfying the requirement. (that is, each person passes the length of the path added up, one way to walk a number of times the length should be calculated). n<=150,m<=20000,1<=k<=10, Edge right <=10000
Analysis: Each point must pass once, there are k individuals, which let us think of the network flow of the DAG's least-weight path coverage problem, but here the graph is an acyclic graph and there are some sequential restrictions, and points and edges can be used multiple times. However, each point is only destroyed once, from this point of view, We consider all the points that a person destroys in turn, they must satisfy the number increment, that is, "a person destroys a numbered point, and if it does not stop, it will destroy a larger number than it", as if there were some features of the DAG. Looking closely, we find that If a person destroys point u and then destroys Point V, the shortest path length required is a short-circuit from U to V only through points that are less than V, which can be preprocessed. Can Floyd, also can n times Dijkstra. I think Dijkstra better understand, Each run through the point of the number less than s to reach the shortest path to s, you can directly limit the number of points passed. So we built a n+1 point of the race map, the edge from the small point U point to the number of points V, edge right for a person to destroy u and then go to v the shortest (after the point is less than V), Indicates the shortest path from 0 to V, and also the point with a number less than V.
Then, apart from 0 and N, each point is split into points and out points (0 only out points, N only in points)
For an edge (U,V), an in point from the out point of U to V is connected to the edge of the edge
From the source point to 1 to n-1 the out point of each point with a flow rate of 1 to 0 of the edge
One flow from the source point to 0 with a K-fee of 0 (limit K individuals)
A flow from the in point of each point to a meeting point is a 1-charge 0 edge, and the scheme for each maximum flow on the graph corresponds to a feasible scheme. Run the minimum cost maximum flow.
#include <cstdio>#include<cstring>#include<algorithm>#include<queue>using namespacestd;intn,m,k;intd[155][155];namespacemincost{Const intmaxn= -, maxm=300000; structedge{intTo,next,w,cost; }LST[MAXM];intlen=0, FIRST[MAXM]; voidAddedge (intAintBintWintCost ) {lst[len].to=b;lst[len].next=first[a];lst[len].w=w;lst[len].cost=cost;first[a]=len++; Lst[len].to=a;lst[len].next=first[b];lst[len].w=0; lst[len].cost=-cost;first[b]=len++; } BOOLINQ[MAXN];intq[maxn],dis[maxn],vis[maxn],prt[maxn],head,tail,s,t,t; BOOLSPFA () {head=tail=0; q[tail++]=s;dis[s]=0;p rt[s]=-1; vis[s]=++t;inq[s]=true; while(head!=tail) { intx=q[head++];head%=maxn;inq[x]=false; for(intPT=FIRST[X];p t!=-1;p t=Lst[pt].next) { if(lst[pt].w==0)Continue; if(vis[lst[pt].to]!=t| | dis[lst[pt].to]>dis[x]+lst[pt].cost) {Dis[lst[pt].to]=dis[x]+lst[pt].cost;vis[lst[pt].to]=T; Prt[lst[pt].to]=pt; if(!Inq[lst[pt].to]) {Q[tail++]=lst[pt].to;inq[lst[pt].to]=true; tail%=MAXN; } } } } returnvis[t]==u; } intMincost () {intans=0; while(SPFA ()) {ans+=Dis[t]; for(intPt=prt[t];p t!=-1;p t=prt[lst[pt^1].to]) {LST[PT].W--;lst[pt^1].w++; } } returnans; } voidbuild () {memset (First,-1,sizeof(first)); S=2*n+1; t=2*n+2; Addedge (s),0K0); for(intI=1; i<=n;++i) Addedge (S,i,1,0); for(intI=1; i<=n;++i) Addedge (N+i,t,1,0); for(intI=1; i<=n;++i) Addedge (0, N+i,1, d[0][i]); for(intI=1; i<=n;++i) { for(intj=i+1; j<=n;++j) {Addedge (I,n+j,1, D[i][j]); } } }};namespaceinit{Const intmaxn= $, maxm=40005; structedge{intto,next,w; }LST[MAXM];intlen=1, FIRST[MAXN]; voidAddedge (intAintBintW) {lst[len].to=b;lst[len].next=first[a];lst[len].w=w;first[a]=len++; } intDIS[MAXN];BOOLVIS[MAXN]; structnode{intv,d; Node (int_v,int_d) {v=_v;d=_d; } BOOL operator< (ConstNode &b)Const{ returnD>B.D; } }; voidDijkstraints) {memset (Vis,0,sizeof(VIS)); Priority_queue<node>Q; Q.push (node (s),0)); while(!Q.empty ()) {Node TMP=q.top (); Q.pop (); if(VIS[TMP.V])Continue; VIS[TMP.V]=true;d is[tmp.v]=TMP.D; for(intPT=FIRST[TMP.V];p t;pt=Lst[pt].next) { if(Lst[pt].to<s&&!vis[lst[pt].to]) Q.push (node (lst[pt].to,lst[pt].w+tmp.d)); } } for(intI=0; i<=s;++i) d[i][s]=Dis[i]; } voidinit () {scanf ("%d%d%d",&n,&m,&k); inta,b,w; for(intI=1; i<=m;++i) {scanf ("%d%d%d",&a,&b,&W); Addedge (a,b,w); Addedge (B,A,W); } memset (d,0x3f,sizeof(d)); for(intI=1; i<=n;++i) Dijkstra (i); } };intMain () {init::init (); Mincost::build (); printf ("%d\n", Mincost::mincost ()); return 0;}
BZOJ2324[ZJOI2011] Rescue Pikachu