[NOIP 2013]货车运输
想要求货车的最大载重量,根据木桶原理,我们就希望一条路径上的载重量的最小值最大。让一条路径上的载重量的最小值最大,贪心得想,如果我加进去的每条边都是剩余边中最大的那一个,那么在形成完整的通路时,一条路径上的边一定是所有情况中最大的那一种,这个思想很明显就是最大生成树。
LCA找路径求最小值就好了。
1 #include <iostream>
2 #include <algorithm>
3 #include <cstdio>
4 using namespace std;
5 const int maxn=1e5+10;
6 const int inf=1e9;
7 int n,m;
8 struct edge{
9 int to,next,w;
10 }ed[maxn];
11 struct node{
12 int x,y,dis;
13 }pos[maxn];
14 int head[maxn],tot;
15 void add(int u,int to,int w){
16 ed[++tot].w=w;
17 ed[tot].to=to;
18 ed[tot].next=head[u];
19 head[u]=tot;
20 }
21 int fa[maxn];
22 void init(){
23 for(int i = 1;i <= n;i++) fa[i]=i;
24 }
25 int find(int x){
26 if (fa[x]==x) return x;
27 else return fa[x]=find(fa[x]);
28 }
29 void update(int x,int y){
30 int fx=find(x),fy=find(y);
31 fa[fx]=fy;
32 }
33 bool cmp(node x,node y){
34 return x.dis>y.dis;
35 }
36 void tree(){
37 sort(pos+1,pos+m+1,cmp);
38 init();
39 for (int i = 1;i <= m;i++){
40 int x=pos[i].x,y=pos[i].y,w=pos[i].dis;
41 if (find(x)!=find(y)){
42 update(find(x),find(y));
43 add(x,y,w);add(y,x,w);
44 }
45 }
46 }
47 int vis[maxn],dep[maxn],w[maxn][30],f[maxn][30];
48 void dfs(int x){
49 vis[x]=1;
50 for (int i = head[x];i;i=ed[i].next){
51 int to=ed[i].to;
52 if (vis[to]) continue;
53 dep[to]=dep[x]+1;
54 f[to][0]=x;
55 w[to][0]=ed[i].w;
56 dfs(to);
57 }
58 }
59 int lca(int x,int y){
60 if (find(x)!=find(y)) return -1;
61 int ans=inf;
62 if (dep[x]>dep[y]) swap(x,y);
63 for (int i = 20;i >= 0;i--){
64 if (dep[f[y][i]]>=dep[x]){
65 ans=min(ans,w[y][i]);
66 y=f[y][i];
67 }
68 }
69 if (x==y) return ans;
70 for (int i = 20;i>= 0;i--){
71 if (f[x][i]!=f[y][i]){
72 ans=min(ans,min(w[x][i],w[y][i]));
73 x=f[x][i];
74 y=f[y][i];
75 }
76 }
77 ans=min(ans,min(w[x][0],w[y][0]));
78 return ans;
79 }
80 int main(){
81 int x,y,z,q;
82 scanf ("%d%d",&n,&m);
83 for (int i = 1;i <= m;i++){
84 scanf ("%d%d%d",&x,&y,&z);
85 pos[i].x=x,pos[i].y=y,pos[i].dis=z;
86 }
87 tree();
88 for (int i = 1;i <= n;i++){
89 if (!vis[i]){
90 dep[i]=1;
91 dfs(i);
92 f[i][0]=i;
93 w[i][0]=inf;
94 }
95 }
96 for (int i= 1;i <= 20;i++){
97 for (int j = 1;j <= n;j++){
98 f[j][i]=f[f[j][i-1]][i-1];
99 w[j][i]=min(w[j][i-1],w[f[j][i-1]][i-1]);
100 }
101 }
102 scanf ("%d",&q);
103 for (int i = 1;i <= q;i++){
104 scanf ("%d%d",&x,&y);
105 printf("%d\n",lca(x,y));
106 }
107 return 0;
108 }
另一道题UVA11354 Bond就是反过来,求最小生成树,LCA求最大值