zoukankan      html  css  js  c++  java
  • CodeForces160D 最小生成树 + dfs

    https://cn.vjudge.net/problem/26727/origin

    题目大意:

    给一个带权的无向图,保证没有自环和重边. 由于最小生成树不唯一,因此你需要确定每一条边是以下三种情况哪一个 1.一定在所有MST上 2.可能在某个MST上 3.一定不可能在任何MST上 输入

    第一行给出n,m表示点数和边数. 数据范围见原题面 之后m行,每行给出ai,bi,wi 表示一个边的两个端点和边的权值.保证没有自环与重边. 输出

    一看到这题就觉得似曾相似,仔细一看是某场比赛里卡了我三个小时的类似题,当时由于题解写的和我写的算法不一样,没有去补题。这次遇到这题偶然发现由于这题的数据开大了,之前那题的暴力算法走不通了,正好用到了我之前写了很久没找出bug的算法。

    第一步显然是将所有边按权值从小到大排序,将每层权值相同的边分开来做。

    第二步显然是将每层所有两点已经联通的点打上none的标记

    问题在于分开必通过和可以不通过的边,上次只想到了dfs,也想到将所有已联合的点形成联通快找联通快之间必连的点,这次看了题解,发现这种联通块之间必须链接的点被称为桥,必须连接的点成为割点,寻找桥和割点都是通过tarjan算法实现的,也就是基于dfs打一个时间戳实现。

    所以我们只要每一层进行见图找出所有的桥即可解决问题。

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Scl(x) scanf("%lld",&x);  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x);  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    typedef vector<int> VI;
    const double eps = 1e-9;
    const int maxn = 1e5 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,M,tmp,K,tot,index; 
    int tree[maxn];
    int type[maxn];
    int vis[maxn];
    int head[maxn];
    struct Query{
        int u,v,w,id;
    }q[maxn];
    struct Edge{
        int v,next,id;
    }edge[maxn * 2];
    bool cmp(Query a,Query b){
        return a.w < b.w;
    }
    int find(int p){
        if(p == tree[p]) return p;
        return tree[p] = find(tree[p]);
    }
    void Union(int a,int b){
        a = find(a); b = find(b);
        tree[a] = b;
    }
    void add(int u,int v,int id){
        edge[tot].v = v;
        edge[tot].next = head[u];
        edge[tot].id  = id;
        head[u] = tot++;
    }
    int dfs(int u,int last){
        int lowu = vis[u] = ++index;
        for(int i = head[u]; ~i;i = edge[i].next){
            int v = edge[i].v; 
            if(!vis[v]){
                int lowv = dfs(v,i);
                lowu = min(lowu,lowv);
                if(lowv > vis[u]) type[edge[i].id] = 2;
            }else if(vis[v] < vis[u] && i != (last ^ 1)){
                lowu = min(lowu,vis[v]);
            }
        }
        return lowu;
    }
    int main()
    {
        scanf("%d%d",&N,&M);
        For(i,1,M) scanf("%d%d%d",&q[i].u,&q[i].v,&q[i].w),q[i].id = i;
        sort(q + 1,q + 1 + M,cmp);
        For(i,1,N) tree[i] = i;
        For(i,1,M){
            int j = i;
            while(j <= M && q[j].w == q[i].w)j++; j--;
            For(k,i,j){
                q[k].u = find(q[k].u);q[k].v = find(q[k].v);
                int u = q[k].u; int v = q[k].v;
                if(u == v){
                    type[q[k].id] = 0;
                    continue;
                }
                type[q[k].id] = 1;
                vis[u] = vis[v] = 0;
                head[u] = head[v] = -1; 
            }
            index = tot = 0;
            For(k,i,j){
                if(q[k].u != q[k].v){
                    add(q[k].u,q[k].v,q[k].id);
                    add(q[k].v,q[k].u,q[k].id);
                }
            }
            For(k,i,j) if(!vis[q[k].u]) dfs(q[k].u,-1);
            For(k,i,j) Union(q[k].u,q[k].v);
            i = j;
        }
        For(i,1,M){
            if(!type[i]) puts("none");
            else if(type[i] == 2)puts("any");
            else puts("at least one");
        }
        #ifdef VSCode
        system("pause");
        #endif
        return 0;
    }
  • 相关阅读:
    JUnit测试框架的简单使用
    [转载文章] 单元测试与单元测试框架
    [转载文章]单元测试基本准则
    [转载文章]Google的Java编程风格指南(Java编码规范)
    设计模式实战——开发中经常涉及到的建造者模式
    痞子衡嵌入式:ARM Cortex-M文件那些事(7)- 反汇编文件(.s/.lst/.dump)
    痞子衡嵌入式:ARM Cortex-M文件那些事(6)- 可执行文件(.out/.elf)
    痞子衡嵌入式:ARM Cortex-M文件那些事(5)- 映射文件(.map)
    痞子衡嵌入式:ARM Cortex-M文件那些事(4)- 可重定向文件(.o/.a)
    痞子衡嵌入式:ARM Cortex-M文件那些事(3)- 工程文件(.ewp)
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/9622936.html
Copyright © 2011-2022 走看看