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

来源:互联网 发布:龙腾管家软件下载 编辑:程序博客网 时间:2024/05/16 04:02

题目:

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;}


0 0
原创粉丝点击