您的位置:首页 > 产品设计 > UI/UE

HDU 3721 - Building Roads(DFS`树的直径)

2015-10-01 19:55 344 查看
题目:

http://acm.hdu.edu.cn/showproblem.php?pid=3721

题意:

n个点的有边权的树,移动一条边(即改变边的两个端点),使得树的直径最短。

思路:

移动的边在原树的直径上,移动后原树变成两棵子树,求出两棵子树的直径。

枚举子树直径上的点,决定移动边的两个端点,求出最小的距离。

AC.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 2505;

int tot, head[maxn];
struct Edge{
int to, w, next;
}edge[maxn*2];
void init()
{
tot = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int w)
{
edge[tot].to = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
}

int num[maxn];
int res, point;
void dfs(int u, int fa)
{
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to, w = edge[i].w;
if(v == fa) continue;
num[v] = num[u] + w;
if(res < num[v]) {
res = num[v];
point = v;
}
dfs(v, u);
}
}
struct Path{
int to, id;
}path[maxn];

void dfs1(int u, int fa)
{
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to, w = edge[i].w;
if(v == fa) continue;
num[v] = num[u] + w;
path[v].to = u; path[v].id = i;
if(res < num[v]) {
res = num[v];
point = v;
}
dfs1(v, u);
}
}

int now;
int smpath[maxn];
int nog1, nog2;

void dfsmall(int u, int fa)
{
if(u == now) return;
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to, w = edge[i].w;
if(nog1 == i || nog2 == i) continue;

if(v == fa) continue;
num[v] = num[u] + w;
if(res < num[v]) {
res = num[v];
point = v;
}
dfsmall(v, u);
}
}
void dfsmall2(int u, int fa)
{
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to, w = edge[i].w;
if(nog1 == i || nog2 == i) continue;

if(v == fa) continue;
num[v] = num[u] + w;
smpath[v] = u;
if(res < num[v]) {
res = num[v];
point = v;
}
dfsmall2(v, u);
}
}

void initdfs()
{
res = 0;
memset(num, 0, sizeof(num));
}
int main()
{
// freopen("in", "r", stdin);
int TT, ca = 1;
scanf("%d", &TT);
while(TT--) {
int n;
scanf("%d", &n);
init();
int u, v, w;
for(int i = 1; i < n; ++i) {
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
addedge(v, u, w);
}

memset(path, -1, sizeof(path));
int S, T;
initdfs(); dfs(1, 1);
S = point;
initdfs(); dfs1(S, S);
T = point;

//printf("%d, %d\n", S, T);

int ans = inf, r;

int s1, t1, s2, t2, p1, p2;
for(int i = T; ~i; i = path[i].to) {

int id = path[i].id;
if(id == -1) break;
int u = edge[id].to, v = edge[id^1].to;
nog1 = id; nog2 = id^1;

r = edge[id].w;

memset(smpath, -1, sizeof(smpath));
initdfs(); dfsmall(u, u);
s1 = point;
initdfs(); dfsmall2(s1, s1);
t1 = point;
int r1 = num[t1];

// printf("****(%d, %d) = %d\n", s1, t1, num[t1]);

int tmp = inf;
for(int j = t1; ~j; j = smpath[j]) {
int cnt = max(num[t1]-num[j], num[j]);
tmp = min(tmp, cnt);
}
// printf("half path = %d\n", tmp);
r += tmp;

memset(smpath, -1, sizeof(smpath));
initdfs(); dfsmall(v, v);
s2 = point;
initdfs(); dfsmall2(s2, s2);
t2 = point;
int r2 = num[t2];

// printf("****(%d, %d) = %d\n", s2, t2, num[t2]);

tmp = inf;
for(int j = t2; ~j; j = smpath[j]) {
int cnt = max(num[t2]-num[j], num[j]);
tmp = min(tmp, cnt);
}
// printf("half path = %d\n", tmp);
r += tmp;

//printf("(%d, %d) = %d\n\n", u, v, r);
r = max(r, max(r1, r2));

ans = min(ans, r);
}
printf("Case %d: %d\n", ca++, ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU