删边

来源:互联网 发布:mac版cad和windows 编辑:程序博客网 时间:2024/06/18 09:12

删边
(delete)
题目描述:
给出 N 个点,N-1 条边的连通图.
现要求删除一条边,使得连通块的直径总和最大.所谓连通块的直径是指连通块中最远两
点之间的距离。
问:直径总和最大是多少?
输入:
文件名为 delete.in
第一行正整数 N.
接下来 N-1 行.每行两个数,A,B,LEN 表示 A,B(1<=A,B<=N)有一条长度为 Len(1<=Len<=1000)
的边连接着.
输出:
文件名为 delete.out
一个数 Ans.直径总和的最大值.
样例输入:
10
2 1 982
3 1 169
4 1 934
5 1 325
6 1 735
7 1 675
8 2 302
9 3 450
10 5 173
样例输出:
2668
数据范围:
30% N<=100
70% N<=5000
100% N<=100000

以下为70暴力写法T-T;;;;

program df;
type point=^node;
node=record
date,ends:longint;
next:point;
end;
var i,j,n,m,x,y,z,k,t,z1,z2,sum,r,max:longint;
path:array[0..100000] of point;
a,c,d,e,g,h:array[0..100000] of longint;
b:array[0..100000] of boolean;
f:array[0..100,0..100] of longint;

procedure com(x,y,z:longint);
var i:point;
begin
i:=path[x];
new(path[x]);
path[x]^.ends:=y;
path[x]^.date:=z;
path[x]^.next:=i;
end;

procedure dfs(x,z:longint);
var i:point;
y,u:longint;
begin
if z>max then begin max:=z; r:=x; end;
b[x]:=true;
i:=path[x];
while i<>nil do
begin
y:=i^.ends;
if not b[y] then dfs(y,z+i^.date);
i:=i^.next;
end;
d[x]:=0;
end;

function deal(x,y:longint):longint;
begin
max:=-maxlongint;
fillchar(b,sizeof(b),false);
b[x]:=true; b[y]:=true;
dfs(x,0);
if r=x then exit(0); //r为以x为起点找到的最长边的终点
fillchar(b,sizeof(b),false);
b[r]:=true; b[y]:=true;
dfs(r,0); //以r为起点找到的一定是最长边(想想为什么)
exit(max);
end;

begin
assign(input,’delete.in’);
reset(input);
assign(output,’delete.out’);
rewrite(output);
readln(n); k:=0;
for i:=1 to n-1 do
begin
readln(x,y,z);
com(x,y,z);
com(y,x,z);
a[i]:=x; c[i]:=y;
end;
t:=0;
for i:=1 to n-1 do
begin
x:=a[i]; y:=c[i];
z1:=deal(x,y);
z2:=deal(y,x); //两个连通块分别求解
if z1+z2>t then t:=z1+z2;
end;

writeln(t);
close(input);
close(output);
end.

最近研究出新的七十分算法

program df;
type point=^node;
node=record
date,ends:longint;
next:point;
end;
var i,j,n,m,x,y,z,k,t,sum1,sum2,ans,k2:longint;
path:array[0..200000] of point;
a,b,c,d,f:array[0..1000] of longint;
g:array[0..1000,0..1000] of longint;
ff,f2:array[0..1000] of boolean;
procedure com(x,y,z:longint);
var i:point;
begin
i:=path[x];
new(path[x]);
path[x]^.ends:=y;
path[x]^.date:=z;
path[x]^.next:=i;
end;

procedure dfs(x:longint);
var i:point;
y:longint;
begin
ff[x]:=true;
f2[x]:=true;
//writeln(x);
i:=path[x];
while i<>nil do
begin
y:=i^.ends;
if not ff[y] then dfs(y);
i:=i^.next;
end;
ff[x]:=false;
end;

procedure search(t,x:longint);
var i:point;
y:longint;
begin
ff[x]:=true;
i:=path[x];
while i<>nil do
begin
y:=i^.ends;
if not ff[y] then
begin
g[t,y]:=g[t,x]+i^.date;
search(t,y);
end;
i:=i^.next;
end;
ff[x]:=false;
end;

begin
assign(input,’delete.in’);
reset(input);
assign(output,’delete.out’);
rewrite(output);

readln(n);
if n>1000 then
begin
ans:=0; sum1:=maxlongint;
for i:=1 to n-1 do
begin
readln(x,y,z);
ans:=ans+z;
if sum1>z then sum1:=z;
end;
writeln(ans-sum1);
close(input);
close(output);
halt;
end;

for i:=1 to n-1 do
begin
readln(x,y,z);
inc(d[x]);
inc(d[y]);
com(x,y,z);
com(y,x,z);
a[i]:=x; b[i]:=y;
end;

for i:=1 to n do
search(i,i);

k:=0;
for i:=1 to n do
if d[i]=1 then
begin
inc(k);
f[k]:=i;
end;
ans:=0;
for t:=1 to n-1 do
begin
fillchar(f2,sizeof(f2),false);
sum1:=0; sum2:=0;
x:=a[t]; y:=b[t];
k2:=0;
if d[x]=2 then begin inc(k2); f[k2+k]:=a[t]; end;
if d[y]=2 then begin inc(k2); f[k2+k]:=b[t]; end;
ff[x]:=true;
dfs(y);
ff[x]:=false;
for i:=1 to k+k2 do
if not f2[f[i]] then
for j:=1 to k+k2 do
if not f2[f[j]] then
if f[i]<>f[j] then
begin
if g[f[i],f[j]]>sum1 then sum1:=g[f[i],f[j]];
end;
for i:=1 to k do
if f2[f[i]] then
for j:=1 to k do
if f2[f[j]] then
if f[i]<>f[j] then
begin
if g[f[i],f[j]]>sum2 then sum2:=g[f[i],f[j]];
end;
if sum1+sum2>ans then ans:=sum1+sum2;
end;
writeln(ans);
close(input);
close(output);
end.

原创粉丝点击