• NOIP2013D1T3货车运输(最大生成树+倍增lca)


    传送门

    这道题,先用kruskal求一遍图中的最大生成树。

    然后,倍增求lca,求lca的同时求出边权的最小值。

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    
    int n, m, cnt, q, t, k;
    int f[10001], head[100001], p[10001][21], minn[10001][21], deep[10001];
    bool vis[10001];
    struct node
    {
        int x, y, z;
    }tree[100001];
    struct Node
    {
        int next, to, val;
    }edge[100001];
    
    inline void add(int a, int b, int c)
    {
        edge[cnt].val = c;
        edge[cnt].to = b;
        edge[cnt].next = head[a];
        head[a] = cnt++;
    }
    
    inline int father(int a)
    {
        return a == f[a] ? a : f[a] = father(f[a]);
    }
    
    inline bool cmp(node a, node b)
    {
        return a.z > b.z;
    }
    
    void kruskal()
    {
        int i;
        for(i = 1; i <= m; i++)    scanf("%d %d %d", &tree[i].x, &tree[i].y, &tree[i].z);
        for(i = 1; i <= n; i++) f[i] = i;
        std::sort(tree + 1, tree + m + 1, cmp);
        for(i = 1; i <= m; i++)
        {
            int fa = father(tree[i].x), fb = father(tree[i].y);
            if(fa != fb)
            {
                f[fa] = fb;
                add(tree[i].x, tree[i].y, tree[i].z);
                add(tree[i].y, tree[i].x, tree[i].z);
            }
            if(k == n - 1) break;
        }
    }
    
    void dfs(int i)
    {
        int j;
        vis[i] = 1;
        for(j = head[i]; j != -1; j = edge[j].next)
         if(!vis[edge[j].to])
         {
             deep[edge[j].to] = deep[i] + 1;
             p[edge[j].to][0] = i;
             minn[edge[j].to][0] = edge[j].val;
             dfs(edge[j].to);
         }
    }
    
    void init()
    {
        int i, j;
        for(j = 1; (1 << j) <= n; j++)
         for(i = 1; i <= n; i++)
         {
             p[i][j] = p[p[i][j - 1]][j - 1];
             minn[i][j] = std::min(minn[i][j - 1], minn[p[i][j - 1]][j - 1]);
         }
    }
    
    int lca(int a, int b)
    {
        int i, j, ret = 707406378;
        if(deep[a] < deep[b]) std::swap(a, b);
        for(i = 0; (1 << i) <= deep[a]; i++);
        i--;
        for(j = i; j >= 0; j--)
         if(deep[a] - (1 << j) >= deep[b])
         {
             ret = std::min(ret, minn[a][j]);
             a = p[a][j];
         }
        if(a == b) return ret;
        for(j = i; j >= 0; j--)
         if(p[a][j] != p[b][j])
         {
             ret = std::min(ret, std::min(minn[a][j], minn[b][j]));
             a = p[a][j];
             b = p[b][j];
         }
        ret = std::min(ret, std::min(minn[a][0], minn[b][0]));
        return ret;
    }
    
    int main()
    {
        int i, j, x1, y1;
        scanf("%d %d", &n, &m);
        memset(head, -1, sizeof(head));
        //memset(minn, 127 / 3, sizeof(minn));
        kruskal();
        for(i = 1; i <= n; i++)
         if(!vis[i])
         {
             deep[i] = 1;
             dfs(i);
         }
        init();
        scanf("%d", &q);
        for(i = 1; i <= q; i++)
        {
            scanf("%d %d", &x1, &y1);
            if(father(x1) != father(y1)) printf("-1
    ");
            else printf("%d
    ", lca(x1, y1));
         }
        return 0;
    
    }
    View Code

    换了写法

    惨啊,

    i >= 0 我居然nc的用 i 代替

    应该是 i >= 1 用 i 代替

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 
      5 const int MAXN = 10001, MAXM = 50001, INF = 707406378;
      6 int n, m, q, cnt, tot;
      7 int head[MAXM], to[MAXM << 1], next[MAXM << 1], val[MAXM << 1];
      8 int f1[MAXN], f[MAXN][21], min[MAXN][21], deep[MAXN];
      9 
     10 struct node
     11 {
     12     int x, y, z;
     13 }p[MAXM];
     14 
     15 inline bool cmp(node a, node b)
     16 {
     17     return a.z > b.z;
     18 }
     19 
     20 inline void add(int x, int y, int z)
     21 {
     22     to[cnt] = y;
     23     val[cnt] = z;
     24     next[cnt] = head[x];
     25     head[x] = cnt++;
     26 }
     27 
     28 inline int find(int x)
     29 {
     30     return x == f1[x] ? x : f1[x] = find(f1[x]);
     31 }
     32 
     33 inline int Min(int x, int y)
     34 {
     35     return x < y ? x : y;
     36 }
     37 
     38 inline void swap(int &x, int &y)
     39 {
     40     x ^= y ^= x ^= y;
     41 }
     42 
     43 inline void dfs(int u)
     44 {
     45     int i, v;
     46     deep[u] = deep[f[u][0]] + 1;
     47     for(i = 0; f[u][i]; i++)
     48         f[u][i + 1] = f[f[u][i]][i],
     49         min[u][i + 1] = Min(min[u][i], min[f[u][i]][i]);
     50     for(i = head[u]; i ^ -1; i = next[i])
     51     {
     52         v = to[i];
     53         if(!deep[v])
     54         {
     55             f[v][0] = u;
     56             min[v][0] = val[i];
     57             dfs(v);
     58         }
     59     }
     60 }
     61 
     62 inline int lca(int x, int y)
     63 {
     64     int i, ans = INF;
     65     if(deep[x] < deep[y]) swap(x, y);
     66     for(i = 20; i >= 0; i--)
     67         if(deep[f[x][i]] >= deep[y])
     68             ans = Min(ans, min[x][i]), x = f[x][i];
     69     if(x == y) return ans == INF ? -1 : ans;
     70     for(i = 20; i >= 0; i--)
     71         if(f[x][i] ^ f[y][i])
     72             ans = Min(ans, min[x][i]),
     73             ans = Min(ans, min[y][i]),
     74             x = f[x][i], y = f[y][i];
     75     ans = Min(ans, min[x][0]);
     76     ans = Min(ans, min[y][0]);
     77     return ans == INF ? -1 : ans;
     78 }
     79 
     80 int main()
     81 {
     82     //freopen("truck.in", "r", stdin);
     83     //freopen("truck.out", "w", stdout);
     84     int i, x, y, fx, fy;
     85     scanf("%d %d", &n, &m);
     86     memset(head, -1, sizeof(head));
     87     memset(min, 127 / 3, sizeof(min));
     88     for(i = 1; i <= m; i++) scanf("%d %d %d", &p[i].x, &p[i].y, &p[i].z);
     89     std::sort(p + 1, p + m + 1, cmp);
     90     for(i = 1; i <= n; i++) f1[i] = i;
     91     for(i = 1; i <= m; i++)
     92     {
     93         fx = find(p[i].x);
     94         fy = find(p[i].y);
     95         if(fx ^ fy)
     96         {
     97             f1[fx] = fy;
     98             tot++;
     99             add(p[i].x, p[i].y, p[i].z);
    100             add(p[i].y, p[i].x, p[i].z);
    101         }
    102         if(tot == n - 1) break; 
    103     }
    104     for(i = 1; i <= n; i++)
    105         if(!deep[i])
    106             dfs(i);
    107     scanf("%d", &q);
    108     for(i = 1; i <= q; i++)
    109     {
    110         scanf("%d %d", &x, &y);
    111         if(find(x) ^ find(y)) puts("-1");
    112         else printf("%d
    ", lca(x, y));
    113     }
    114     return 0;
    115 }
    View Code
  • 相关阅读:
    find文件及目录后的一些操作
    Firefox关闭GET请求到detectportal.firefox.com网站的方法
    Shell脚本自定义批量生成ip
    Nginx关闭危险的HTTP请求
    个人总结
    软件工程第二次作业--结对编程
    软件工程第一次作业
    C#中使用存储过程返回值的问题(转)
    使用SqlDataAdapter时,需要注意的几点(转)
    Sql连接查询(转)
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6667614.html
Copyright © 2020-2023  润新知