zoukankan      html  css  js  c++  java
  • POJ1679 The Unique MST【次小生成树】

    题意:

    判断最小生成树是否唯一。

    思路:

    首先求出最小生成树,记录现在这个最小生成树上所有的边,然后通过取消其中一条边,找到这两点上其他的边形成一棵新的生成树,求其权值,通过枚举所有可能,通过这些权值看与原最小生成树的权值比较看其是否唯一。其实也可以理解成次小生成树加上最大边权的边后是否唯一。

    代码:

    krusual:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    
    typedef long long ll;
    const int N=11000;
    const int M=15005;
    int i,j,n,m,cnt,parent[N];
    bool flag;
    
    struct man
    {
        int u,v,w;
        int eq,used,del;
    } edg[N];
    
    bool cmp(man g,man h)
    {
    return g.w<h.w;
    }
    
    void init()
    {
        for(i=0; i<=10005; i++)
        {
            parent[i]=i;
        }
    }
    
    int Find(int x)
    {
        if(parent[x] != x) parent[x] = Find(parent[x]);
        return parent[x];
    }//查找并返回节点x所属集合的根节点
    
    void Union(int x,int y) {
        x = Find(x);
        y = Find(y);
        if(x == y) return;
        parent[y] = x;
    }//将两个不同集合的元素进行合并
    
    int Kruskal()
    {
        init();
        int sum=0;
        int num=0;
        for(i=0;i<m;i++)
        {
            if(edg[i].del==1)continue;
            int u=edg[i].u;int v=edg[i].v;int w=edg[i].w;
            if(Find(u)!=Find(v))
            {
                sum+=w;
                if(!flag)edg[i].used=1;
                num++;
                Union(u,v);
            }
            if(num>=n-1)break;
       }
       return sum;
    }
    
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            cnt=0;
            cin>>n>>m;
            for(i=0; i<m; i++)
            {
                cin>>edg[i].u>>edg[i].v>>edg[i].w;
                edg[i].del=0;
                edg[i].used=0;
                edg[i].eq=0;//eq没有初始化
            }
            for(i=0;i<m;i++)
            {
                for(j=0;j<m;j++)
                {
                    if(i==j)continue;
                    if(edg[i].w==edg[j].w)edg[i].eq=1;
                }
            }
            sort(edg,edg+m,cmp);
            flag=false;
            cnt=Kruskal();
            flag=true;
            bool gg=false;
            for(i=0;i<m;i++)
            {
                if(edg[i].used==1&&edg[i].eq==1)
                {
                    edg[i].del=1;
                    int s=Kruskal();//printf("%d %d
    ",i,s);
                    if(s==cnt)
                    {
                        gg=true;
                        cout<<"Not Unique!"<<endl;
                        break;
                    }
                    edg[i].del=0;
                }
            }
            if(!gg) cout<<cnt<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    JS 实现数据分割1,123,456
    JS屏蔽键盘相关事件
    地图坐标转屏幕坐标
    对xml格式的字符串的一些操作
    ListView_Adpter
    单元测试(Android)_JUnit
    调用系统拍照
    获取手机SD卡的剩余容量(MB)
    数据库的基本操作
    临时修改模拟器手机运行内存和手机内存(不是SD卡内存)
  • 原文地址:https://www.cnblogs.com/darklights/p/7638175.html
Copyright © 2011-2022 走看看