zoukankan      html  css  js  c++  java
  • Codeforces 160D Edges in MST

    最近发现,不写题解不长记性。

    题意:给出一张带权无向图,然后询问该图的每条边进行询问,若这条边出现在该图的所有最小生成树中,输出any;若这条边可以出现在这张图的某几个最小生成树中,输出at least once;若这条边不会出现在这张图的任意一个最小生成树中,输出none。

    解法:跟求最小生成树的方法类似,首先将所有边按照权值从小到大排序,一次取出所有边长相等的边,查询每条边的两个节点是否在同一集合中,若不在同一集合中,则在这两个集合间添加一条无向边,同时认为这些边有可能出现在该图的最小生成树中。再做tarjan找桥,找到桥将一定出现在该图的最小生成树中。然后将所有的边的两个端点合并到同一集合,在合并到同一集合的过程中,同时清除该在集合上的所有的边。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define maxn 100010
    using namespace std;
    
    struct Edge{
        int from,to,dist,id;
    }a[maxn];
    
    int first[maxn],v[maxn*2],next[maxn*2],id[maxn*2];
    int ans[maxn],fa[maxn],pre[maxn],dfs_clock,e;
    
    int cmp(Edge a,Edge b){
        return a.dist < b.dist;
    }
    void init(){
        e = 0;
        memset(first,-1,sizeof(first));
    }
    
    void add_edge(int a,int b,int ID){
        v[e] = b;
        next[e] = first[a];
        id[e] = ID;
        first[a] = e++;
    }
    
    int dfs(int u,int fa_id){
        int lowu = pre[u] = ++dfs_clock;
        for(int i = first[u];i != -1;i = next[i]){
            if(!pre[v[i]]){
                int lowv = dfs(v[i],id[i]);
                lowu = min(lowu,lowv);
                if(lowv > pre[u])   ans[id[i]] = 1;
            }else if(pre[v[i]] < pre[u] && id[i] != fa_id){
                lowu = min(lowu,pre[v[i]]);
            }
        }
        return lowu;
    }
    
    int find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]);}
    
    void join(int x,int y){
        int fx = find(x);
        int fy = find(y);
        if(fx != fy){
            e = 0;
            first[fx] = first[fy] = -1;
            pre[fx] = pre[fy] = 0;
            fa[fx] = fy;
        }
    }
    
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        init();
        for(int i = 1;i <= n;i++)   fa[i] = i;
        dfs_clock = 0;
        for(int i = 0;i < m;i++){
            scanf("%d%d%d",&a[i].from,&a[i].to,&a[i].dist);
            a[i].id = i;
        }
        sort(a,a+m,cmp);
        memset(pre,0,sizeof(pre));
        memset(ans,0,sizeof(ans));
        for(int i = 0;i < m;i++){
            int j = i+1;
            while(j < m && a[i].dist == a[j].dist)    j++;
            for(int k = i;k < j;k++){
                int fx = find(a[k].from);
                int fy = find(a[k].to);
                if(fx != fy){
                    add_edge(fx,fy,a[k].id);
                    add_edge(fy,fx,a[k].id);
                    ans[a[k].id] = 2;
                }
            }
            for(int k = i;k < j;k++){
                int fx = find(a[k].from);
                int fy = find(a[k].to);
                if(fx != fy && !pre[fx]){
                    dfs(fx,-1);
                }
            }
            for(int k = i;k < j;k++){
                join(a[k].from,a[k].to);
            }
            i = j - 1;
        }
        for(int i = 0;i < m;i++){
            if(ans[i] == 0) printf("none
    ");
            else if(ans[i] == 1)    printf("any
    ");
            else    printf("at least one
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    拼接sql ()
    HttpPostedFileBase 基类
    jQuery获取Select元素
    HttpFileCollection 类使用
    C# 截取字符串——
    判断人员js
    删除PLSQL 关联表
    mongodb常用操作方法
    json返回取值操作
    idhttp请求网址中的中文输入
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3232745.html
Copyright © 2011-2022 走看看