zoukankan      html  css  js  c++  java
  • poj1679,次小生成树的学习

    昨天总结MST的模板,也写的差不多了吧

    总之两种方法,kruskal和prim

    麻烦的可能就是生成MST的唯一性的判定

    原理很简单,先找MST,然后枚举MST上每条边,方法是删除该边再找MST,如果能找到MST并且权值等于第一次找到的,就不唯一了

    http://poj.org/problem?id=1679

    # include <iostream>
    # include <cstdio>
    # include <algorithm>
    # include <cstring>
    using namespace std;
    
    
    //先求出最小生成树,然后删除这棵树上的每条边求MST,求的时候要判断是否是MST
    struct edge{
        int u, v, w, f;
        friend bool operator < (const edge &a, const edge &b){
            return a.w < b.w;
        }
    }e[100 * 100 + 10];
    int pre[110];
    int n, m;
    int find(int x){
        int s;
        for(s = x; pre[s] >= 0; s = pre[s]);
        while(s != x){
            int t = pre[x];
            pre[x] = s;
            x = t;
        }
        return s;
    }
    void Union(int x, int y){
        int u = find(x);
        int v = find(y);
        if(u == v) return;//如果在同一棵树上
        if(pre[u] > pre[v]){
            pre[u] += pre[v];
            pre[v] = u;
        }else{
            pre[v] += pre[u];
            pre[u] = v;
        }
    }
    int kruskal(int f){
        int w = 0;
        int num = 0;
        memset(pre, -1, sizeof pre);
        for(int i = 0; i < m; i ++){
            if(e[i].f == 2) continue;
            int u = e[i].u;
            int v = e[i].v;
            if(find(u) != find(v)){
                w += e[i].w;
                if(f)e[i].f = 1;
                num ++;
                Union(u, v);
            }
            if(num >= n - 1)
              break;
        }
        if(num == n-1)
        return w;
        else return -1;//说明没有找到MST
    }
    int main(){
        int tcase;
        scanf("%d", &tcase);
        while(tcase --){
            scanf("%d%d", &n, &m);
            for(int i = 0; i < m; i ++){
                scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
                e[i].f = 0;
            }
            sort(e, e + m);
            int w = kruskal(1);
            int flag = 0;
            for(int i = 0; i < m; i ++){
                if(e[i].f == 0)continue;
                e[i].f ++;
                int tmp = kruskal(0);
                e[i].f --;
                //printf("%d ---\n", tmp);
                if(tmp != -1 && tmp == w){
                    flag = 1;
                    break;
                }
            }
            if(flag)
              puts("Not Unique!");
            else
              printf("%d\n", w);
        }
        return 0;
    }
    
    
    /*
    //牛人做法,拿来当模板用
    int const INF=1000000000;
    int const maxn=105;
    int mark[maxn],map[maxn][maxn],mst[maxn];
    int n,m;
    void prim(){
        int i,j,k,ans=0,min,v,flag=0;
        for (i=1;i<=n;i++){
            mark[i]=0;
            mst[i]=map[1][i];
        }
        mark[1]=1;
        for (i=1;i<n;i++){
            min=INF;
            for (j=1;j<=n;j++){
                if (!mark[j] && mst[j]<min){
                    min=mst[j];
                    v=j;
                }
            }
            k=0;
            //------------------------------
            //如果要选的点到已选的点,还有一条边权值相同,就 NO 了
            for (j=1;j<=n;j++){
                if (mark[j] && min==map[v][j])k++;
            }
            if (k>1){flag=1;break;}
            //------------------------------
            ans+=min;
            mark[v]=1;
            for (j=1;j<=n;j++){
                if (!mark[j] && map[v][j]<mst[j])mst[j]=map[v][j];
            }
        }
        if (flag)cout<<"Not Unique!"<<endl;
        else cout<<ans<<endl;
    }
    int main()
    {
        int cas,i,j,p,q,w;
        cin>>cas;
        while (cas--)
        {
            cin>>n>>m;
            for (i=1;i<=n;i++)
                for (j=1;j<=n;j++)
                    map[i][j]=INF;
            while (m--)
            {
                cin>>p>>q>>w;
                map[q][p]=map[p][q]=w;
            }
            prim();
        }
        return 0;
    }
    */
  • 相关阅读:
    linux 网卡配置详情
    linux ftp 添加用户及权限管理
    mysql 权限管理
    linux ftp 安装及相关命令
    linux find 命令
    linux yum 安装及卸载
    linux svn 安装
    cssText方式写入css
    addLoadEvent
    mobile体验效果:增加点击后反馈
  • 原文地址:https://www.cnblogs.com/louzhang/p/2619423.html
Copyright © 2011-2022 走看看