标签:
滑雪场坐落在FJ省西北部的若干座山上。从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向。你的团队负责每周定时清理雪道。你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部。从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道。由于每次飞行的耗费是固定的,为了最小化耗费,你想知道如何用最少的飞行次数才能完成清理雪道的任务。
program xjt7; const maxn = 110;maxm = 100010;INF = 10000000007; var n,m,e,s,t,x,y:int64; i,j:longint; fa,next,link,w,cost,rec,son:array[-1..maxm]of int64; dis,opt,pos,pre,b,lea:array[-1..maxn]of int64; vis:array[-1..maxn]of boolean; function min(a,b:int64):int64; begin if a<b then exit(a) else exit(b); end; procedure add(x,y,z,cst:int64); begin inc(e);fa[e]:=y;next[e]:=link[x];link[x]:=e;w[e]:=z;cost[e]:=cst;rec[e]:=e+1;son[e]:=x; inc(e);fa[e]:=x;next[e]:=link[y];link[y]:=e;w[e]:=0;cost[e]:=-cst;rec[e]:=e-1;son[e]:=y; end; function spfa:boolean; var head,tail,x,j:int64; begin fillchar(vis,sizeof(vis),true); fillchar(dis,sizeof(dis),63); head:=0;tail:=1;opt[1]:=s;dis[s]:=0;vis[s]:=false; while head<>tail do begin head:=(head+1) mod maxn; x:=opt[head];j:=link[x]; while j<>0 do begin if (w[j]>0)and(dis[x]+cost[j]<dis[fa[j]]) then begin dis[fa[j]]:=dis[x]+cost[j];pre[fa[j]]:=j; if vis[fa[j]] then begin vis[fa[j]]:=false; tail:=(tail+1) mod maxn; opt[tail]:=fa[j]; end; end; j:=next[j]; end; vis[x]:=true; end; if dis[t]<>dis[t+1] then exit(true); exit(false); end; procedure MCMF; var sum,u,mn,ans:int64; begin ans:=0; while spfa do begin sum:=0; u:=t;mn:=INF; while u<>s do begin mn:=min(mn,w[pre[u]]); u:=son[pre[u]]; end; u:=t; while u<>s do begin inc(sum,mn*cost[pre[u]]); dec(w[pre[u]],mn);inc(w[rec[pre[u]]],mn); u:=son[pre[u]]; end; if sum>0 then break; inc(ans,mn); end; writeln(ans); end; begin //assign(input,‘xjt7.in‘);reset(input); readln(n); fillchar(b,sizeof(b),0); for i:=1 to n do begin read(lea[i]); for j:=1 to lea[i] do begin read(y);add(i,y,1,-INF);add(i,y,INF,0); inc(b[y]); end; readln; end; s:=0;t:=n+1; for i:=1 to n do if b[i]=0 then add(s,i,INF,1); for i:=1 to n do if lea[i]=0 then add(i,t,INF,1); MCMF; end.
标签:
原文地址:http://www.cnblogs.com/mjy0724/p/4463023.html