P1967 [NOIP2013 提高组] 货车运输

Posted acmloser

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1967 [NOIP2013 提高组] 货车运输相关的知识,希望对你有一定的参考价值。

原题链接

考察:LCA+最大生成树

思路:

       实际是求两点之间最大的最短边.这样很容易想到二分,但是直接二分会TLE.

       然后又会想到次小生成树,但是这道题边不能构成树.由于我们要的边尽量大,可以考虑贪心一波建立最大生成树.然后求两点之间的最小距离直接套LCA倍增板子.这题比次小生成树省事.

       时间复杂度O(mlog2n+q*log2n)

  1 #include <iostream> 
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <queue>
  5 using namespace std;
  6 const int N = 10010,M = 50010,INF = 0x3f3f3f3f;
  7 int n,m,idx,Q,p[N],h[N],depth[N],fa[N][16],d[N][16];
  8 struct Road{
  9     int fr,to,ne,w;
 10 }road[M<<1];
 11 struct Path{
 12     int u,v,w;
 13     bool operator<(const Path& p)const{
 14         return this->w>p.w;
 15     }
 16 }path[M];
 17 void add(int a,int b,int w)
 18 {
 19     road[idx].w =w,road[idx].fr = a,road[idx].to = b,road[idx].ne = h[a],h[a] = idx++;
 20 }
 21 int findf(int x)
 22 {
 23     if(p[x]!=x) p[x] = findf(p[x]);
 24     return p[x];
 25 }
 26 void bfs(int s)
 27 {
 28     queue<int> q;
 29     memset(depth,0x3f,sizeof depth);
 30     depth[s] = 1,depth[0] = 0;
 31     q.push(s);
 32     while(q.size())
 33     {
 34         int u = q.front();
 35         q.pop();
 36         for(int i=h[u];~i;i=road[i].ne)
 37         {
 38             int v = road[i].to;
 39             if(depth[v]>depth[u]+1)
 40             {
 41                 depth[v] = depth[u]+1;
 42                 q.push(v);
 43                 fa[v][0] = u; d[v][0] = road[i].w;
 44                 for(int j=1;j<15;j++)
 45                 {
 46                     int anc = fa[v][j-1];
 47                     fa[v][j] = fa[anc][j-1];
 48                     d[v][j] = min(d[anc][j-1],d[v][j-1]);
 49                 }
 50             }
 51         }
 52     }
 53 }
 54 int lca(int a,int b)
 55 {
 56     int ans = INF;
 57     if(depth[a]<depth[b]) swap(a,b);
 58     for(int i=14;i>=0;i--)
 59       if(depth[fa[a][i]]>=depth[b])
 60       {
 61           ans = min(d[a][i],ans);
 62           a = fa[a][i];
 63       }
 64     if(a!=b)
 65     {
 66         for(int i=14;i>=0;i--)
 67          if(fa[a][i]!=fa[b][i]) 
 68          {
 69              ans = min(ans,d[a][i]);
 70              ans = min(ans,d[b][i]);
 71              a = fa[a][i];
 72              b = fa[b][i];
 73          }
 74         ans = min(ans,d[a][0]);
 75         ans = min(ans,d[b][0]);
 76     }
 77     return ans;
 78 }
 79 void build()
 80 {
 81     sort(path+1,path+m+1);
 82     for(int i=1;i<=m;i++)
 83     {
 84         int pa = findf(path[i].u),pb = findf(path[i].v),w = path[i].w;
 85         if(pa==pb) continue;
 86         p[pa] = pb;
 87         add(path[i].u,path[i].v,path[i].w);
 88         add(path[i].v,path[i].u,path[i].w);
 89     }
 90 }
 91 int main()
 92 {
 93     scanf("%d%d",&n,&m);
 94     for(int i=1;i<=n;i++) h[i] = -1,p[i] = i;
 95     for(int i=1;i<=m;i++)
 96     {
 97         int a,b,w; scanf("%d%d%d",&a,&b,&w);
 98         path[i] = {a,b,w};
 99     }
100     build();
101     bfs(1);
102     scanf("%d",&Q);
103     while(Q--) 
104     {
105         int a,b; scanf("%d%d",&a,&b);
106         if(findf(a)!=findf(b)) printf("-1\\n");
107         else printf("%d\\n",lca(a,b));
108     }
109     return 0;
110 }

 

以上是关于P1967 [NOIP2013 提高组] 货车运输的主要内容,如果未能解决你的问题,请参考以下文章

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

[NOIP2013提高组]货车运输

[luogu P1967][NOIp2013]P1967 货车运输

[NOIP2013 提高组] 货车运输

3287 货车运输 2013年NOIP全国联赛提高组 40 分

NOIP2013提高组货车运输