POJ1679-The Unique MST

大致说下题意:有多个case 给出n m , n代表点数,m代表边数,之后给出m条边,该图的最小生成树是不是唯一的。

主要做法就是先用prim求出最小生成树,尝试在加入一条生成树外的边,并删除一条在树内的边,若该操作后,得到的值和原来一样就说明生成树不唯一。

另外,要注意不联通的情况,这是也输出"Not Unique!"
附代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#include<memory>
using namespace std;
typedef long long ll;
#define clr(name,value) memset(name,value,sizeof(name))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int inf = 0x3f3f3f3f, maxn = 100100;

int n,m,t,ans;
int g[105][105],d[105],pre[105],Max[105][105];
bool vis[105],used[105][105];

bool prim(){
    clr(vis,0);   
    clr(d,inf);
    clr(pre,-1);
    clr(used,0);   //表示该边有没有被访问过
    clr(Max,0);
    d[1]=0;
    pre[1]=0;
    ans=0;
    int i,j,k,minn;
    for(i=1;i<=n;i++){
        minn=inf;
        for(j=1;j<=n;j++){
            if(!vis[j]&&minn>d[j]){
                k=j;
                minn=d[j];
            }
        }
        if(minn==inf)
            return 1;  //如果是非连通图 返回1
        vis[k]=1;
        used[k][pre[k]]=used[pre[k]][k]=1;
        ans+=d[k];

        for(j=1;j<=n;j++){
            if(vis[j]) Max[k][j]=Max[j][k]=max(Max[j][pre[k]],d[k]);      
            //Max[j][k]表示从j到k的路径中最大的边,非常重要!
            if(!vis[j]&&d[j]>g[k][j]){
                d[j]=g[k][j];
                pre[j]=k;
            }
        }
    }
    return 0;
}
int main()
{
    //freopen("f:/in.txt","r",stdin);
    int i,j,u,v,w;
    scanf("%d",&t);
    while(t--){
        clr(g,inf);
        g[0][1]=g[1][0]=0;
        scanf("%d%d",&n,&m);
        for(i=0;i<m;i++){
            scanf("%d%d%d",&u,&v,&w);
            if(g[u][v]>w)
                g[u][v]=g[v][u]=w;
        }
        if(prim()){
            puts("Not Unique!");
            continue;
        }
        int Min=inf;
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++){
                if(i!=j&&!used[i][j]){
                    Min=min(Min,ans+g[i][j]-Max[i][pre[i]]);
                }
            }
        if(Min==ans)
            puts("Not Unique!");
        else
            printf("%d\n",ans);
    }
    return 0;
}

下面给出几组数据吧
3

5 6
1 2 1
1 5 2
2 5 3
2 3 2
3 4 6
2 4 4
答案:9

4 5
1 2 1
2 3 3
1 3 3
1 4 2
2 4 2
答案:Not Unique!

4 4
1 2 1
3 4 2
1 3 3
2 4 3
答案:Not Unique!
这组数据很有价值!正因为类似这种数据,才需要用到Max这个二维数组!!

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值