[NOI2003]逃学的小孩

嘟嘟嘟

 

题中说任意两个点之间只有唯一1条路径,意思就是这是个树~

概括一下,就是求min(c->a, c->b) + a->b 的最大值。

显然,让整体最大,那就让这两项最大即可,a->b的最大值显然就是树的直径,跑两遍bfs(最短路)就行。

至于第一项,枚举c,每一次求出a->c, b->c的两者之中最小值,然后求这些最小值的最大值就行了~~

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #include
 7 #include
 8 #include
 9 #include
10 #include
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(' ')
14 #define Mem(a) memset(a, 0, sizeof(a))
15 typedef long long ll;
16 typedef double db;
17 const int INF = 0x3f3f3f3f;
18 const int eps = 1e-8;
19 const int maxn = 2e5 + 5;
20 inline ll read()
21 {
22     ll ans = 0;
23     char ch = getchar(), last = ' ';
24     while(!isdigit(ch)) {last = ch; ch = getchar();}
25     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
26     if(last == '-') ans = -ans;
27     return ans;
28 }
29 inline void write(ll x)
30 {
31     if(x < 0) x = -x, putchar('-');
32     if(x >= 10) write(x / 10);
33     putchar(x % 10 + '0');
34 }
35 
36 int n, m;
37 vector<int> v[maxn];
38 vector c[maxn];
39 
40 #define pr pair
41 #define mp make_pair
42 bool in[maxn];
43 ll disA[maxn], disB[maxn];
44 int dijkstra(int s, ll* dis)
45 {
46     Mem(in); 
47     for(int i = 1; i <= n; ++i) dis[i] = (ll)INF * (ll)INF;
48     dis[s] = 0;
49     priority_queue, greater > q;
50     q.push(mp(dis[s], s));
51     while(!q.empty())
52     {
53         int now = q.top().second; q.pop();
54         if(in[now]) continue;
55         in[now] = 1;
56         for(int i = 0; i < (int)v[now].size(); ++i)
57         {
58             if(dis[v[now][i]] > dis[now] + c[now][i])
59             {
60                 dis[v[now][i]] = dis[now] + c[now][i];
61                 q.push(mp(dis[v[now][i]], v[now][i]));
62             }
63         }
64     }
65     ll Max = 0; int pos;
66     for(int i = 1; i <= n; ++i) if(dis[i] > Max) Max = dis[i], pos = i;
67     return pos;
68 }
69 
70 int main()
71 {
72     n = read(); m = read();
73     for(int i = 1; i <= m; ++i) 
74     {
75         int x = read(), y = read(); ll co = read();
76         v[x].push_back(y); c[x].push_back(co);
77         v[y].push_back(x); c[y].push_back(co);
78     }
79     int a = dijkstra(1, disA);
80     int b = dijkstra(a, disA);
81     dijkstra(b, disB);
82     ll Max = 0;
83     for(int i = 1; i <= n; ++i)
84         Max = max(Max, min(disA[i], disB[i]));
85     write(disA[b] + Max); enter;
86     return 0;
87 }
View Code

话说回来,我刚开始用bfs跪了三个点(不是TLE),改成dijkstra就过了,为啥咧……树上两点间路径既然是唯一的,那么只要有一个合理的遍历顺序就行了啊……求助各界大佬。

转载于:https://www.cnblogs.com/mrclr/p/9561739.html

你可能感兴趣的:([NOI2003]逃学的小孩)