所以我们可以把每个顶点理解成两个顶点,一个是出发,一个是目标,建立二分图模型。该二分图的任何一个匹配方案,都对应了一个路径覆盖方案。如果匹配数为0,那么显然路径数=顶点数。每增加一条匹配边,那么路径覆盖数就减少一个,所以路径数=顶点数 - 匹配数。要想使路径数最少,则应最大化匹配数,所以要求二分图的最大匹配。
program minroad;const maxn=1000;var g:array[0..maxn,0..maxn]of longint;f:array[0..maxn,0..maxn]of boolean;que,d:array[0..maxn]of longint;v:array[0..maxn]of boolean;n,m,ans,i:longint;procedure init;var i,j,u,v:longint;beginread(n,m);fillchar(g,sizeof(g),0);fillchar(f,sizeof(f),false);for i:=1 to n do g[0][i]:=1;for i:=1 to n do g[i+n][n+n+1]:=1;for i:=1 to m dobeginread(u,v);g[u][v+n]:=1;f[u][v+n]:=true;end;end;function min(a,b:longint):longint;beginif a<b then exit(a) else exit(b);end;function bfs(s,t:longint):boolean;var l,r,u,i:longint;beginfillchar(que,sizeof(que),0);fillchar(d,sizeof(d),0);fillchar(v,sizeof(v),false);l:=0;r:=1;que[l]:=s;v[s]:=true;while l<r dobeginu:=que[l];for i:=0 to n+n+1 doif (g[u][i]>0)and(not v[i]) thenbeginque[r]:=i;inc(r);v[i]:=true;d[i]:=d[u]+1;end;inc(l);end;exit(v[t]);end;function dfs(p,a,t:longint):longint;var i,f,flow:longint;beginif (a=0)or(p=t) then exit(a);flow:=0;for i:=0 to n+n+1 doif (g[p][i]>0)and(d[i]=d[p]+1) thenbeginf:=dfs(i,min(g[p][i],a),t);if f=0 then continue;inc(flow,f);dec(g[p][i],f);inc(g[i][p],f);dec(a,f);if a=0 then break;end;exit(flow);end;function dinic(s,t:longint):longint;var ans:longint;beginans:=0;while bfs(s,t) doans:=ans+dfs(s,maxlongint,t);exit(ans);end;procedure print(p:longint);var i:longint;beginwrite(p,' ');v[p]:=true;for i:=n+1 to n+n doif (g[p][i]=0)and(f[p][i])and(not v[i]) then print(i-n);end;beginassign(input,'f.in');reset(input);init;ans:=n-dinic(0,n+n+1);fillchar(v,sizeof(v),false);for i:=1 to n do if not v[i] then begin print(i);writeln;end;write(ans);close(input);end.
评论