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 }
View Code

倍增数组开小了调了好久

两个倍增写穿了调了好久

我太菜了

以上是关于luogu p1967 noip2013 火车运输的主要内容,如果未能解决你的问题,请参考以下文章

luogu1967noip2013 货车运输 [生成树kruskal LCA ]

P1967 [NOIP2013 提高组] 货车运输

NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)

洛谷P1967 [NOIP2013提高组Day1T2]货车运输

NOIP 2013 火车运输Kruskal + 树链剖分

luogu P1967 货车运输