poj 1679 次小生成树
次小生成树的求法:
1.Prime法
定义一个二维数组F[i][j]表示点i到点j在最小生成树中的路径上的最大权值。有个知识就是将一条不在最小生成树中的边Edge加入最小生成树时,树中要去掉的边就是Edge连接的两个端点i,j的F[i][j]。这样就能保存找到的生成树时次小生成树。
代码如下:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define inf 1<<30
#define Maxn 102
#define Maxm 10010
#define USE 2
#define EXIST 1
#define NOTEXIST 0
using namespace std;
int map[Maxn][Maxn],dist[Maxn],vi[Maxn],f[Maxn][Maxn],use[Maxn][Maxn],pre[Maxn];
int n,m;
int prime(int src)
{
int i,j,Min,index;
int ans=;
memset(vi,,sizeof(vi));
memset(pre,-,sizeof(pre));
for(i=;i<=n;i++)
dist[i]=inf;//一定要初始化为inf,这样以第一个点开始,使与第一个相连的节点的前节点为第一个节点。
dist[]=;//以第一个节点开始
for(i=;i<=n;i++)
{
Min=inf;
for(j=;j<=n;j++)
{
if(!vi[j]&&dist[j]<Min)
{
Min=dist[j];
index=j;
}
}
if(pre[index]!=-)//如果存在前节点
{
use[index][pre[index]]=use[pre[index]][index]=USE;//标记为使用过
for(j=;j<=n;j++)
if(vi[j])//对树种已存在的点进行更新
f[j][index]=max(f[j][pre[index]],map[index][pre[index]]);
}
ans+=Min;
vi[index]=;
//cout<<Min<<"*"<<endl;
for(j=;j<=n;j++)
{
if(!vi[j]&&dist[j]>map[index][j])
{
dist[j]=map[index][j];
pre[j]=index;
}
}
}
//cout<<ans<<"*"<<endl;
return ans;
}
int secondmst(int mst)
{
int i,j,ans;
ans=inf;
for(i=;i<=n;i++)
for(j=;j<=n;j++)
if(use[i][j]==EXIST)
{
if(mst+map[i][j]-f[i][j]<ans)//求次小生成树
ans=mst+map[i][j]-f[i][j];
}
//cout<<ans<<"*"<<endl;
return ans;
}
void init()//初始化
{
int i,j;
memset(f,,sizeof(f));
for(i=;i<=Maxn-;i++)
for(j=;j<=Maxn-;j++)
map[i][j]=map[j][i]=inf;
memset(use,,sizeof(use));
}
int main()
{
int i,j,a,b,c,t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(i=;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
map[a][b]=map[b][a]=c;
use[a][b]=use[b][a]=;
}
int ans1=prime();
int ans2=secondmst(ans1);
if(ans1==ans2)
printf("Not Unique!\n");
else
printf("%d\n",ans1);
}
return ;
}
kruskaer的算法就相对简单,就是先求一边最下生成树,将树中的边保存下来。然后每次去掉一个边,重求最小生成树,找出最小的便是次小生成树。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
struct Edge{
int x,y,c;
int operator <(const Edge &temp) const
{
return c<temp.c;
}
}edge[];
int set[],e,vi[],p[],index;
int find(int x)
{
if(x!=set[x])
set[x]=find(set[x]);
return set[x];
}
void init()
{
e=;
index=;
for(int i=;i<=;i++)
set[i]=i;
memset(vi,,sizeof(vi));
}
int main()
{
int t,n,m,i,j,x,y,c;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&n,&m);
for(i=;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&c);
edge[i].x=x,edge[i].y=y,edge[i].c=c;
}
sort(edge+,edge+m+);
int num=;
int ans=;
for(i=;i<=m;i++)//先求一边最小生成树
{ //cout<<edge[i].c<<"*"<<endl;
x=find(edge[i].x);
y=find(edge[i].y);
if(x==y)
continue;
p[index++]=i;//将树中的每条边保存起来
set[x]=y;
ans+=edge[i].c;
num++;
if(num==n-)
break;
}
int ans2=,num2=;
int f=;
for(i=;i<index;i++)//在枚举每次删除一条边后,求最小生成树
{
for(j=;j<=;j++)
set[j]=j;
ans2=,num2=;
for(j=;j<=m;j++)
{
if(j==p[i])
continue;
x=find(edge[j].x);
y=find(edge[j].y);
if(x==y)
continue;
set[x]=y;
ans2+=edge[j].c;
num2++;
if(num2==n-)
break;
}
if(num2!=n-)
continue;
if(ans==ans2)//若删除某条边后的最小权值与原来相同,那么最小生成树不唯一
{
f=;
break;
}
}
if(!f)
printf("%d\n",ans);
else
printf("Not Unique!\n");
}
return ;
}
poj 1679 次小生成树的更多相关文章
- The Unique MST POJ - 1679 次小生成树prim
求次小生成树思路: 先把最小生成树求出来 用一个Max[i][j] 数组把 i点到j 点的道路中 权值最大的那个记录下来 used数组记录该条边有没有被最小生成树使用过 把没有使用过的一条边加 ...
- The Unique MST POJ - 1679 (次小生成树)
Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spann ...
- poj 2831 次小生成树模板
/*次小生成树 题意:给你一些路径,现在将一部分路径权值减少后问是否可以替代最小生成树里面的边. 解:次小生成树,即将这条边连上,构成一个环 求出任意两点路径之间的除了这条边的最大值,比较这个最大值& ...
- The Unique MST-POJ1679(次小生成树)
http://poj.org/problem?id=1679 次小生成树 #include<stdio.h> #include<string.h> #include<st ...
- POJ1679 The Unique MST[次小生成树]
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 28673 Accepted: 10239 ...
- POJ 1679 The Unique MST (次小生成树)
题目链接:http://poj.org/problem?id=1679 有t组数据,给你n个点,m条边,求是否存在相同权值的最小生成树(次小生成树的权值大小等于最小生成树). 先求出最小生成树的大小, ...
- poj 1679 The Unique MST 【次小生成树】【模板】
题目:poj 1679 The Unique MST 题意:给你一颗树,让你求最小生成树和次小生成树值是否相等. 分析:这个题目关键在于求解次小生成树. 方法是,依次枚举不在最小生成树上的边,然后加入 ...
- poj 1679 The Unique MST 【次小生成树+100的小数据量】
题目地址:http://poj.org/problem?id=1679 2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2 Sample Outpu ...
- POJ 1679 The Unique MST:次小生成树【倍增】
题目链接:http://poj.org/problem?id=1679 题意: 给你一个图,问你这个图的最小生成树是否唯一. 题解: 求这个图的最小生成树和次小生成树.如果相等,则说明不唯一. 次小生 ...
随机推荐
- js获取服务端IP及端口及协议
alert("location:"+window.location); alert("href: "+window.location.href); alert( ...
- 【Todo】ipcs命令学习
可以先看这一篇 http://www.jb51.net/article/40805.htm
- sql server2008添加登录账户配置权限 && 登录时18456错误
1.如何为SQL Server2008添加登录账户并配置权限 2.SQLSERVER2008 18456错误 http://blog.csdn.net/goodshot/article/details ...
- Castle IOC容器快速入门
主要内容 1.为什么要IOC 2.什么是Castle IOC容器 3.快速入门示例 4.几个重要的概念 一,为什么要IOC IOC(控制反转或者叫依赖注入)Martin Fowler大师在他的文章中已 ...
- C++多态实现(虚函数,成员函数覆盖、隐藏)
// 1.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> using namespace ...
- SQLServer2008设置开启INTERNET远程连接
SQL Server 2008默认是不允许远程连接的,sa帐户默认禁用的,如果想要在本地用SSMS连接远程服务器上的SQL Server 2008,需要做两个部分的配置: 使用sa账户登录SQL Se ...
- SQL 表锁(转)
其实你可以使用事务处理 比方说在一个字段里面添加一个boolean 的字段当你要处理该字段的时候就 True 哪么别的人都不可以进行操作 如果是False 哪么就可以进行操作--呵可--我是这样的 ...
- 小学生玩ACM----广搜
Oil Deposits Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tot ...
- WCF 新手教程二
基本知识: [ServiceContract] Attribute 能够有以下Property 的: CallbackContract 设置callback的类型:Duplicate指Service ...
- Gym 100637F F. The Pool for Lucky Ones 暴力
F. The Pool for Lucky Ones Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10 ...