zoukankan      html  css  js  c++  java
  • 常州模拟赛d7t3 水管

    分析:第一问还是很好做的,关键是怎么做第二问.我们可以每次删掉最小生成树上的一条边,然后再求一次最小生成树,看边权和大小和原来的是不是一样的,不过这个做法效率很低.

          考虑Kruskal算法的原理,每次加边权最小的边,如果边上的两个点不连通.如果在最小生成树的基础上把不是上面的边给加上去,就会形成环,在环上找除了这条边之外的最大边权,如果等于新加入的这条边,那么就有多个最小生成树.为什么这样呢?我们把最大边拿掉,添加进这条边,两个点还是连通的,边权和一定,只是在Kruskal的时候先考虑了那条最大边而已.

          接下来只需要求出若干对点路径上的最大边权就可以了,我们可以用倍增算法来求.

    写这道题的时候把w数组写成了e[i].w,挂惨了......以后要对同名数组多留意.

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 400010;
    
    int T, n, m, head[maxn], nextt[maxn], to[maxn], w[maxn], tot = 1,fa[maxn],d[maxn],f[maxn][20],dmax[maxn][20];
    long long ans;
    bool flag = false;
    
    struct node
    {
        int u, v, w,use;
    }e[maxn];
    
    void add(int x, int y, int z)
    {
        w[tot] = z;
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    bool cmp(node a, node b)
    {
        return a.w < b.w;
    }
    
    int find(int x)
    {
        if (x == fa[x])
            return x;
        return fa[x] = find(fa[x]);
    }
    
    void dfs(int u, int depth,int from)
    {
        d[u] = depth;
        f[u][0] = from;
        for (int i = head[u]; i; i = nextt[i])
        {
            int v = to[i];
            if (v != from)
            {
                dmax[v][0] = w[i];
                dfs(v, depth + 1, u);
            }
        }
    }
    
    int LCA(int x, int y)
    {
        if (x == y)
            return 0;
        if (d[x] < d[y])
            swap(x, y);
        int maxx = 0;
        for (int i = 19; i >= 0; i--)
            if (d[f[x][i]] >= d[y])
            {
                maxx = max(maxx, dmax[x][i]); 
                x = f[x][i];
            }
        
        if (x == y)
            return maxx;
            
        for (int i = 19; i >= 0; i--)
            if (f[x][i] != f[y][i])
            {
                maxx = max(maxx, max(dmax[x][i], dmax[y][i]));
                x = f[x][i];
                y = f[y][i];
            }
        maxx = max(maxx, max(dmax[x][0], dmax[y][0]));
        return maxx;
    }
    
    int main()
    {
        scanf("%d", &T);
        while (T--)
        {
            memset(head, 0, sizeof(head));
            tot = 1;
            ans = 0;
            flag = false;
            scanf("%d%d", &n, &m);
            memset(d, 0, sizeof(d));
            memset(f, 0, sizeof(f));
            memset(dmax, 0, sizeof(dmax));
            for (int i = 1; i <= n; i++)
                fa[i] = i;
            for (int i = 1; i <= m; i++)
            {
                int a, b, c;
                scanf("%d%d%d", &a, &b, &c);
                e[i].u = a;
                e[i].v = b;
                e[i].w = c;
                e[i].use = 0;
            }
            sort(e + 1, e + 1 + m, cmp);
            for (int i = 1; i <= m; i++)
            {
                int fx = find(e[i].u), fy = find(e[i].v);
                if (fx != fy)
                {
                    add(e[i].u, e[i].v, e[i].w);
                    add(e[i].v, e[i].u, e[i].w);
                    fa[fx] = fy;
                    ans += e[i].w;
                    e[i].use = 1;
                }
            }
            printf("%lld
    ", ans);
            dfs(1, 1,0);
            for (int j = 1; j <= 19; j++)
                for (int i = 1; i <= n; i++)
                {
                    f[i][j] = f[f[i][j - 1]][j - 1];
                    dmax[i][j] = max(dmax[i][j - 1], dmax[f[i][j - 1]][j - 1]);
                }
            for (int i = 1; i <= m; i++)
                if (!e[i].use && LCA(e[i].u, e[i].v) == e[i].w)
                {
                    flag = 1;
                    break;
                }
            if (flag)
                puts("No");
            else
                puts("Yes");
        }
    
        return 0;
    }
  • 相关阅读:
    UVa 291 The House Of Santa Claus——回溯dfs
    (优先)队列简单总结
    POJ 2255 Tree Recovery——二叉树的前序遍历、后序遍历、中序遍历规则(递归)
    博弈论入门 Bash 、Nim 、Wythoff's Game结论及c++代码实现
    UVa 167(八皇后)、POJ2258 The Settlers of Catan——记两个简单回溯搜索
    欧几里得(辗转相除gcd)、扩欧(exgcd)、中国剩余定理(crt)、扩展中国剩余定理(excrt)简要介绍
    51nod 1135 原根 (数论)
    「学习笔记」扩展KMP (简)
    「解题报告」[luoguP6594]换寝室 (二分答案 树形DP)
    「解题报告」[luoguP6585]中子衰变 (交互题 分类讨论)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7610659.html
Copyright © 2011-2022 走看看