luogu p1967 noip2013 火车运输
Posted jack_yyc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu p1967 noip2013 火车运输相关的知识,希望对你有一定的参考价值。
题目大意:
无向图上
每次询问两个点
寻找一条路径使这条路径上的最小值最大
思路:
先跑一个最大生成树
然后在最大生成树上每次对每两个点跑一个lca
在倍增的同时开一个数组a[i][j] 记录从i个点往上跑j条路里j条路中的最小值
然后每次lca的时候顺便记录一下就行了
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<cmath>
5 #include<cstring>
6 #include<cstdlib>
7 #include<set>
8 #include<map>
9 #include<vector>
10 #include<stack>
11 #include<queue>
12 #define ll long long
13 #define inf 2147383611
14 #define MAXN 10101
15 using namespace std;
16 inline int read()
17 {
18 int x=0,f=1;
19 char ch;ch=getchar();
20 while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();}
21 while(isdigit(ch)) {x=x*10+ch-‘0‘;ch=getchar();}
22 return x*f;
23 }
24 struct data
25 {
26 int val,to,from;
27 bool operator < (const data &a) const
28 {
29 return val>a.val;
30 }
31 }edge[MAXN*7];
32 int cnt,n,m,T,to[MAXN*7],first[MAXN],nex[MAXN*7],val[MAXN*7];
33 int depth[MAXN];
34 int father[MAXN];
35 int f[MAXN][20],ans[MAXN][20];
36 int find(int x) {return x==father[x]?x:father[x]=find(father[x]);}
37 bool ok(int a,int b)
38 {
39 int fa=find(a),fb=find(b);
40 if(fa==fb) return 1;
41 else {father[fb]=fa;return 0;}
42 }
43 void add(int u,int v,int a) {nex[++cnt]=first[u],first[u]=cnt,val[cnt]=a,to[cnt]=v;}
44 void kruskal()
45 {
46 int tot=0;
47 for(int i=1;i<=m;i++)
48 {
49 if(!ok(edge[i].from,edge[i].to)) {tot++;add(edge[i].from,edge[i].to,edge[i].val);add(edge[i].to,edge[i].from,edge[i].val);}
50 if(tot==n-1) return ;
51 }
52 }
53 void dfs(int x,int fa)
54 {
55 for(int i=1;i<=17;i++)
56 {
57 if((1<<i)>=depth[x]) break;
58 ans[x][i]=min(ans[x][i-1],ans[f[x][i-1]][i-1]);
59 f[x][i]=f[f[x][i-1]][i-1];
60 }
61 for(int i=first[x];i;i=nex[i]) if(to[i]!=fa) {depth[to[i]]=depth[x]+1,ans[to[i]][0]=val[i],f[to[i]][0]=x;dfs(to[i],x);}
62 }
63 int lca(int u,int v)
64 {
65 if(depth[u]<depth[v]) swap(u,v);
66 int d=depth[u]-depth[v];
67 for(int i=17;i>=0;i--)
68 if(d&(1<<i)) u=f[u][i];
69 for(int i=17;i>=0;i--)
70 {
71 if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
72 }
73 if(u==v) return v;
74 return f[u][0];
75 }
76 int dis(int u,int v)
77 {
78 int res=inf;
79 if(depth[u]<depth[v]) swap(u,v);
80 int d=depth[u]-depth[v];
81 for(int i=17;i>=0;i--)
82 {
83 if(d&(1<<i)) {res=min(res,ans[u][i]);u=f[u][i];}
84 }
85 return res;
86 }
87 int main()
88 {
89 n=read(),m=read();
90 int a,b,c;
91 for(int i=1;i<=n;i++) father[i]=i;
92 for(int i=1;i<=m;i++)
93 {
94 a=read(),b=read(),c=read();
95 edge[i].val=c,edge[i].from=a,edge[i].to=b;
96 }
97 sort(edge+1,edge+m+1);
98 kruskal();
99 int l;
100 depth[1]=1;dfs(1,0);
101 T=read();
102 while(T--)
103 {
104 a=read(),b=read();
105 l=lca(a,b);
106 if(find(a)!=find(b)) printf("-1\n");
107 else printf("%d\n",min(dis(a,l),dis(b,l)));
108 }
109 }
倍增数组开小了调了好久
两个倍增写穿了调了好久
我太菜了
以上是关于luogu p1967 noip2013 火车运输的主要内容,如果未能解决你的问题,请参考以下文章
luogu1967noip2013 货车运输 [生成树kruskal LCA ]
NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)