zoukankan      html  css  js  c++  java
  • [NOIP2013]货车运输

    嘟嘟嘟

    首先,每一辆货车路径唯一,说明应该求生成树。又要满足这条路的最小边权最大,进一步得出要求最大生成树。

    求完最大生成树上要解决的是树上任意两点之间的边权的最小值,我第一反应是树剖维护链上最小值,但其实我们用LCA就可以了:对于任意两点x, y, 维护x到LCA(x, y)和y到LCA(x, y)这两条链上的最小值。时间复杂度O(nlogn)。

    还有几点要注意:

    1.图并不连通,所以对于每一个没遍历过的点都要跑一遍LCA。

    2.好像没啦。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter puts("") 
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const int maxn = 1e5 + 5;
     21 inline ll read()
     22 {
     23     ll ans = 0;
     24     char ch = getchar(), last = ' ';
     25     while(!isdigit(ch)) {last = ch; ch = getchar();}
     26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     27     if(last == '-') ans = -ans;
     28     return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32     if(x < 0) x = -x, putchar('-');
     33     if(x >= 10) write(x / 10);
     34     putchar(x % 10 + '0');
     35 }
     36 
     37 int n, m, q;
     38 vector<int> v[maxn], c[maxn];
     39 struct Edge
     40 {
     41     int x, y, co;
     42     bool operator < (const Edge& other)const
     43     {
     44         return co > other.co;
     45     }
     46 }e[maxn * 5];
     47 
     48 int p[maxn];
     49 void init(int n)
     50 {
     51     for(int i = 1; i <= n; ++i) p[i] = i;
     52 }
     53 int Find(int x)
     54 {
     55     return x == p[x] ? x : p[x] = Find(p[x]);
     56 }
     57 
     58 bool vis[maxn];
     59 int dep[maxn], fa[maxn][21], Min[maxn][21];
     60 void dfs(int now)
     61 {
     62     vis[now] = 1;
     63     for(int i = 1; (1 << i) <= dep[now]; ++i)
     64     {
     65         fa[now][i] = fa[fa[now][i - 1]][i - 1];
     66         Min[now][i] = min(Min[now][i - 1], Min[fa[now][i - 1]][i - 1]);
     67     }
     68     for(int i = 0; i < (int)v[now].size(); ++i)
     69     {
     70         if(!vis[v[now][i]])
     71         {
     72             dep[v[now][i]] = dep[now] + 1;
     73             fa[v[now][i]][0] = now;
     74             Min[v[now][i]][0] = c[now][i];
     75             dfs(v[now][i]);
     76         }
     77     }
     78 }
     79 int lca(int x, int y)
     80 {
     81     int ret = INF;
     82     if(dep[x] < dep[y]) swap(x, y);
     83     for(int i = 20; i >= 0; --i)
     84         if(dep[x] - (1 << i) >= dep[y])
     85         {
     86             if(Min[x][i] != 0)
     87             ret = min(ret, Min[x][i]);
     88             x = fa[x][i];
     89         }
     90     if(x == y) return ret;
     91     for(int i = 20; i >= 0; --i)
     92     {
     93         if(fa[x][i] != fa[y][i])
     94         {
     95             ret = min(ret, Min[x][i]);
     96             ret = min(ret, Min[y][i]);
     97             x = fa[x][i]; y = fa[y][i];
     98         }
     99     }
    100     return min(ret, min(Min[x][0], Min[y][0]));
    101 }
    102 
    103 int main()
    104 {
    105     n = read(); m = read();
    106     init(n);
    107     for(int i = 1; i <= m; ++i) e[i].x = read(), e[i].y = read(), e[i].co = read();
    108     sort(e + 1, e + m + 1);
    109     for(int i = 1, cnt = 0; i <= m; ++i)
    110     {
    111         int px = Find(e[i].x), py = Find(e[i].y);
    112         if(px != py)
    113         {
    114             p[px] = py;
    115             v[e[i].x].push_back(e[i].y); c[e[i].x].push_back(e[i].co);
    116             v[e[i].y].push_back(e[i].x); c[e[i].y].push_back(e[i].co);
    117             if(++cnt == n - 1) break;
    118         }
    119     }
    120     for(int i = 1; i <= n; ++i) if(!vis[i]) dfs(i);    
    121     q = read();
    122     for(int i = 1; i <= q; ++i)
    123     {
    124         int x = read(), y = read();
    125         if(Find(x) == Find(y)) write(lca(x, y)), enter;
    126         else write(-1), enter;
    127     }
    128     return 0;
    129 }
    View Code
  • 相关阅读:
    2013年noip第三题货车运输truck(树链剖分LCA+最大生成树)
    hdu1754线段树入门
    《Spring1之第六次站立会议》
    《Spring1之第五次站立会议》
    《Spring1之第四次站立会议》
    《Spring1之第三次站立会议》
    《 找水王》
    《 Spring1之第二次站立会议(重发)》
    《Spring1之 第一次站立会议(重发)》
    《 第二次站立会议》
  • 原文地址:https://www.cnblogs.com/mrclr/p/9724100.html
Copyright © 2011-2022 走看看