floyd  

一开始脑残地想到强连通分支 tarjan

后来看到数据规模约莫估计不会用这么高深的东西

农民 John的农场里有很多牧区。有的路径连接一些特定的牧区。一片所有连通的牧区称为一个牧场。但是就目前而言,你能看到至少有两个牧区通过任何路径都不连通。这样,Farmer John就有多个牧场了。

John想在农场里添加一条路径(注意,恰好一条)。

如果说像这样 

 A->B->C A和C其实是有路径相连的  也就是说我不能连接A直达C的路径

即只有当两个牧区属于两个不同的牧场(两个不同的连通分支)  才有可能添加路径

 

这点很容易搞错吧。。 一开始就这样WA掉了

 

算法是这样的:

    先用floyd求出任意两个可以互相到达的牧区之间的最短路径,如果两个牧区
    属于不同牧场,则记f[i,j]=maxlongint

 

    记录数组dm[i]表示i牧区所属连通分支离i最远的牧区  到i的距离  ,如果
    此距离>nowmax   ,更新nowmax


    以此求出所有连通分支中直径的最大值
    其实就是求直径最大值记为fmax

    枚举两个属于不同连通分支(即不同牧场)的牧区,(点对<a,b>)
    在之间添加路径,则dm[a]+dm[b]+<a,b>之间直线距离即为  新牧场的直径
    找出最小的直径(题目中要求最小)记为fmin


    如果fmin>fmax 即不管怎样建路径,最后  直径还是大于原先求出的
    输出fmin 否则输出fmax


有个更好理解的版本

     先求最短路,用Floyd就可以了。

 

     算出所有牧场的直径,记其中最大值为pmax

     每个牧区就是一个连通分支,枚举每个点对(a,b)

 

     枚举(a,b)分为位于不同的连通分支,计算连接上以后的形成的新的连通分支的直径,

     就是a,b距离再加上a,b分别位于的分支的直径。然后从所有的点对中找到连接以后形

     成最小直径的牧区记为pmin。

 

     如果 pmin>pmax那么就要输出pmin,这种情况表示新形成的牧区比原来的所有牧区都大

     否则输出pmax

  

  

 

具体见程序

{
ID: xiaweiy1
PROG: cowtour
LANG: PASCAL
}
const maxn=200;     //150
var n,i,j,k:longint;
    tmp,fmax,fmin,nowmax:extended;
    dm:array[1..maxn]of extended;
    f:array[1..maxn,1..maxn]of extended;
    g:array[1..maxn,1..maxn]of longint;
    x,y:array[1..maxn]of longint;
    t:char;
function calc(a,b:longint):extended;
var t,p:extended;
begin
t:=(x[a]-x[b])*(x[a]-x[b]);
p:=(y[a]-y[b])*(y[a]-y[b]);
exit(sqrt(t+p));
end;
begin
assign(input,'cowtour.in');
reset(input);
assign(output,'cowtour.out');
rewrite(output);
readln(n);
for i:=1 to n do
    begin
    readln(x[i],y[i]);
    end;
for i:=1 to n do
    begin
    for j:=1 to n do
        begin
        read(t); g[i,j]:=ord(t)-ord('0');
        if g[i,j]=1 then
           f[i,j]:=calc(i,j)
        else
           f[i,j]:=maxlongint;
        end;
    readln;
    end;
for k:=1 to n do
    begin
    for i:=1 to n do
        begin
        if i<>k then
           begin
           for j:=1 to n do
               begin
               if (i<>j)and(j<>k) then
                  begin
                  if (f[i,k]<>maxlongint)and(f[k,j]<>maxlongint) then
                     if f[i,k]+f[k,j]<f[i,j] then
                        f[i,j]:=f[i,k]+f[k,j];
                  end;
               end;
           end;
        end;
    end;
fmax:=0;
for i:=1 to n do
    begin
    nowmax:=0;
    for j:=1 to n do
        begin
        if i<>j then
           begin
           if (f[i,j]<>maxlongint)and(f[i,j]>nowmax) then
              nowmax:=f[i,j];
           end;
        end;
    dm[i]:=nowmax;    //dismax;
    if nowmax>fmax then fmax:=nowmax;
    end;
fmin:=maxlongint;
for i:=1 to n-1 do
    begin
    for j:=i+1 to n do
        begin
        if (i<>j)and(f[i,j]=maxlongint) then
            begin
            tmp:=calc(i,j);
            if dm[i]+dm[j]+tmp<fmin then
               fmin:=dm[i]+dm[j]+tmp;
            end;
        end;
    end;
if fmin>fmax then fmax:=fmin;
writeln(fmax:0:6);
close(input);
close(output);
end.

posted on 2011-02-12 15:30  Dimfouasstrawberry  阅读(514)  评论(0)    收藏  举报