您的位置:首页 > 理论基础 > 计算机网络

最短路+网络流/sgu 185 Two shortest

2013-03-21 21:50 225 查看
[b]题意[/b]

  求一个无向图中没有重边的两条最短路,并输出方案

[b]分析[/b]

  注意,是两条最短路!不是一条最短一条次短!所以先来个dijkstra/spfa来算一下最短路

  根据dijkstra/spfa求出的dist[i]数组,建立一个新图,上面只有所有满足最短路的边构成的图

  这样,建图就Ok了,下面如何解决没有重边呢?

  很显然,设立一个源点和汇点,在源点出放出2的值。然后把刚刚建好的新图,边的权值设为1,相当于只能允许一个人经过。这样,如果在汇点得到了2的值,说明这样的两条路是存在的,再利用一个dfs求出即可。

  注意dinic需要加上当前弧优化,不然会tle at #17

[b]Accepted Code[/b]

{
PROBLEM:sgu185
AUTHER:Rinyo
MEMO:最短路 网络流
}
Program sgu185;
Const
Infile = 'sgu185.in';
Outfile = '';
Type
Rec = Record
y,s,flow:Longint;
End;
Var
map:Array[0..160000]Of REc;
a:Array[0..430,0..430]Of Longint;
dist,q,num,next,p:Array[0..430]Of Longint;
v:Array[0..430]Of Boolean;
maxflow,i,j,n,m,l:Longint;
flag:Boolean;
Function min(a,b:Longint):Longint;
Begin
if a<b Then min:=a Else min:=b;
End;
Procedure init;
Var
x,y,w:Longint;
Begin
ReadLn(n,m);
For i:=1 To m Do Begin
ReadLn(x,y,w);
a[x,y]:=w;
a[y,x]:=w;
End;
End;
Procedure dijkstra;
Var
j,k,mink:Longint;
begin
Fillchar(dist,sizeof(dist),100);
dist[1]:=0;
For i:=1 To n-1 Do Begin
mink:=maxlongint;
For j:=1 To n Do
If (not v[j]) And (dist[j]<mink) Then Begin
mink:=dist[j];
k:=j;
End;
v[k]:=true;
For j:=1 To n Do
If (a[k,j]>0) And (dist[j]>mink+a[k,j]) Then dist[j]:=mink+a[k,j];
End;
End;

Function dfs(now,value:Longint):Longint;
Var
v1,i,x,ff:Longint;
begin
if now=n Then Begin
dfs:=value;
Exit;
End;
v1:=value;
ff:=p[now];
While ff>-1 Do Begin
i:=map[ff].y;
If (map[ff].flow>0) And (num[i]=num[now]+1) Then begin
x:=dfs(i,min(value,map[ff].flow));
map[ff].flow:=map[ff].flow-x;
value:=value-x;
If odd(ff) Then map[ff+1].flow:=map[ff+1].flow+x
Else map[ff-1].flow:=map[ff-1].flow+x;
End;
ff:=map[ff].s;
If value=0 then break;
End;
p[now]:=ff;
dfs:=v1-value;
End;

Procedure bfs;
Var
head,tail,now,ff,v:Longint;
Begin
Fillchar(q,sizeof(q),0);
Fillchar(num,sizeof(num),0);
head:=0;tail:=1;q[1]:=1;num[1]:=1;flag:=false;
While head<tail Do begin
Inc(head);
now:=q[head];
ff:=next[now];
While ff<>-1 Do Begin
v:=map[ff].y;
If (map[ff].flow>0) And (num[v]=0) Then Begin
num[v]:=num[now]+1;
Inc(tail);
q[tail]:=v;
If v=n Then Begin
flag:=true;
Exit;
End;
End;
ff:=map[ff].s;
End;
End;
End;

Procedure answer(x:Longint);
Var
ff,v:Longint;
Begin
If (x=n) Then Begin
WriteLn(n);
Exit;
End;
ff:=next[x];
While ff<>-1 Do Begin
v:=map[ff].y;
If (map[ff].flow=0) And (a[x,v]+dist[x]=dist[v]) Then begin
Write(x,' ');
answer(v);
map[ff].flow:=1;
Exit;
End;
ff:=map[ff].s;
End;
End;

Begin
Assign(input,infile);Reset(input);
Assign(output,outfile);Rewrite(output);
init;
dijkstra;
l:=0;
Fillchar(next,sizeof(next),$ff);
For i:=1 To n Do
For j:=1 To n Do
If (i<>j) And (a[i,j]>0) Then
If dist[i]+a[i,j]=dist[j] Then Begin
Inc(l);map[l].y:=j;map[l].flow:=1;map[l].s:=next[i];next[i]:=l;
Inc(l);map[l].y:=i;map[l].flow:=0;map[l].s:=next[j];next[j]:=l;
End;
flag:=true;
While flag Do Begin
BFS;
p:=next;
maxflow:=maxflow+dfs(1,2);
End;
//WriteLn(maxflow);
If maxflow<2 Then Begin
WriteLn('No solution');
End Else Begin
answer(1);
answer(1);
End;
Close(input);Close(output);
End.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: