目录

P3761-[TJOI2017]城市

P3761-[TJOI2017]城市

题目:

题目描述:

从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作。这个地区一共有 $n$ 座城市,$n-1$ 条高速公路,保证了任意两运城市之间都可以通过高速公路相互可达,但是通过一条高速公路需要收取一定的交通费用。小明对这个地区深入研究后,觉得这个地区的交通费用太贵。

小明想彻底改造这个地区,但是由于上司给他的资源有限,因而小明现在只能对一条高速公路进行改造,改造的方式就是去掉一条高速公路,并且重新修建一条一样的高速公路(即交通费用一样),使得这个地区的两个城市之间的最大交通费用最小(即使得交通费用最大的两座城市之间的交通费用最小),并且保证修建完之后任意两座城市相互可达。如果你是小明,你怎么解决这个问题?

输入格式:

输入数据的第一行为一个整数 $n$,代表城市个数。

接下来的 $n - 1$ 行分别代表了最初的 $n-1$ 条公路情况。每一行都有三个整数 $u,v,d$。$u,v$ 代表这条公路的两端城市标号,$d$ 代表这条公路的交通费用。

$1 \leq u,v \leq n$,$1\leq d \leq 2000$。

输出格式:

输出数据仅有一行,一个整数,表示进行了最优的改造之后,该地区两城市 之间最大交通费用。

样例:

样例输入1:

1
2
3
4
5
5
1 2 1
2 3 2
3 4 3
4 5 4

样例输出1:

1
7

思路:

实现:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <bits/stdc++.h>
using namespace std;
struct bbbb
{
    int to, nextt, xx;
} b[10010];
int n, tail, dd[5010], dis[5010], vis[5010], ldd, rdd, diss[5010], ttll;
struct llbb
{
    int xxx, x;
} lb[5010];
struct cccc
{
    int zjcd, bjcd, zd;
} cc1[5010], cc2[5010];
void jb(int x, int y, int z)
{
    tail++;
    b[tail].nextt = dd[x];
    b[tail].to = y;
    b[tail].xx = z;
    dd[x] = tail;
    return;
}
queue<int> q;
void bfs(int x)
{
    memset(vis, 0, sizeof(vis));
    dis[x] = 0;
    vis[x] = 1;
    q.push(x);
    while (q.empty() == false)
    {
        int xx = q.front();
        q.pop();
        for (int i = dd[xx]; i != 0; i = b[i].nextt)
        {
            if (vis[b[i].to] == 0)
            {
                vis[b[i].to] = 1;
                dis[b[i].to] = dis[xx] + b[i].xx;
                q.push(b[i].to);
            }
        }
    }
    return;
}
bool dfs(int x, int mb)
{
    if (x == mb)
    {
        ttll++;
        lb[ttll].x = x;
        return true;
    }
    for (int i = dd[x]; i != 0; i = b[i].nextt)
    {
        if (vis[b[i].to] == 0)
        {
            vis[b[i].to] = 1;
            if (dfs(b[i].to, mb) == true)
            {
                ttll++;
                lb[ttll].x = x;
                lb[ttll].xxx = b[i].xx;
                return true;
            }
        }
    }
    return false;
}
int bfs1(int x)
{
    int maxx = 0;
    q.push(x);
    while (q.empty() == false)
    {
        int xx = q.front();
        q.pop();
        maxx = max(maxx, diss[xx]);
        for (int i = dd[xx]; i != 0; i = b[i].nextt)
        {
            if (vis[b[i].to] == 0)
            {
                vis[b[i].to] = 1;
                diss[b[i].to] = diss[xx] + b[i].xx;
                q.push(b[i].to);
            }
        }
    }
    return maxx;
}
int main()
{
    scanf("%d", &n);
    for (int i = 1; i < n; i++)
    {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        jb(x, y, z);
        jb(y, x, z);
    }
    bfs(1);
    for (int i = 1; i <= n; i++)
    {
        if (dis[ldd] <= dis[i])
        {
            ldd = i;
        }
    }
    bfs(ldd);
    for (int i = 1; i <= n; i++)
    {
        if (dis[rdd] <= dis[i])
        {
            rdd = i;
        }
    }
    memset(vis, 0, sizeof(vis));
    vis[ldd] = 1;
    dfs(ldd, rdd);
    memset(vis, 0, sizeof(vis));
    for (int i = 1; i <= ttll; i++)
    {
        vis[lb[i].x] = 1;
    }
    int zhongd = 1;
    for (int i = 2; i <= ttll; i++)
    {
        diss[lb[i].x] = diss[lb[i - 1].x] + lb[i].xxx;
        int qwq = bfs1(lb[i].x);
        if (qwq <= cc1[lb[i - 1].x].zjcd)
        {
            cc1[lb[i].x] = cc1[lb[i - 1].x];
        }
        else
        {
            while (zhongd < i && max(diss[lb[zhongd].x], qwq - diss[lb[zhongd].x]) > max(diss[lb[zhongd + 1].x], qwq - diss[lb[zhongd + 1].x]))
            {
                zhongd++;
            }
            cc1[lb[i].x].zjcd = qwq;
            cc1[lb[i].x].bjcd = max(diss[lb[zhongd].x], qwq - diss[lb[zhongd].x]);
        }
    }
    memset(vis, 0, sizeof(vis));
    memset(diss, 0, sizeof(diss));
    for (int i = 1; i <= ttll; i++)
    {
        vis[lb[i].x] = 1;
    }
    zhongd = ttll;
    for (int i = ttll - 1; i >= 1; i--)
    {
        diss[lb[i].x] = diss[lb[i + 1].x] + lb[i + 1].xxx;
        int qwq = bfs1(lb[i].x);
        if (qwq <= cc2[lb[i + 1].x].zjcd)
        {
            cc2[lb[i].x] = cc2[lb[i + 1].x];
        }
        else
        {
            while (zhongd > i && max(diss[lb[zhongd].x], qwq - diss[lb[zhongd].x]) > max(diss[lb[zhongd - 1].x], qwq - diss[lb[zhongd - 1].x]))
            {
                zhongd--;
            }
            cc2[lb[i].x].zjcd = qwq;
            cc2[lb[i].x].bjcd = max(diss[lb[zhongd].x], qwq - diss[lb[zhongd].x]);
        }
    }
    int minn = 1e9;
    for (int i = 1; i < ttll; i++)
    {
        minn = min(minn, max(cc1[lb[i].x].bjcd + cc2[lb[i + 1].x].bjcd + lb[i + 1].xxx, max(cc1[lb[i].x].zjcd, cc2[lb[i + 1].x].zjcd)));
    }
    printf("%d", minn);
    return 0;
}