次小生成树的求法:

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 次小生成树的更多相关文章

  1. The Unique MST POJ - 1679 次小生成树prim

    求次小生成树思路: 先把最小生成树求出来  用一个Max[i][j] 数组把  i点到j 点的道路中 权值最大的那个记录下来 used数组记录该条边有没有被最小生成树使用过   把没有使用过的一条边加 ...

  2. The Unique MST POJ - 1679 (次小生成树)

    Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spann ...

  3. poj 2831 次小生成树模板

    /*次小生成树 题意:给你一些路径,现在将一部分路径权值减少后问是否可以替代最小生成树里面的边. 解:次小生成树,即将这条边连上,构成一个环 求出任意两点路径之间的除了这条边的最大值,比较这个最大值& ...

  4. The Unique MST-POJ1679(次小生成树)

    http://poj.org/problem?id=1679 次小生成树 #include<stdio.h> #include<string.h> #include<st ...

  5. POJ1679 The Unique MST[次小生成树]

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28673   Accepted: 10239 ...

  6. POJ 1679 The Unique MST (次小生成树)

    题目链接:http://poj.org/problem?id=1679 有t组数据,给你n个点,m条边,求是否存在相同权值的最小生成树(次小生成树的权值大小等于最小生成树). 先求出最小生成树的大小, ...

  7. poj 1679 The Unique MST 【次小生成树】【模板】

    题目:poj 1679 The Unique MST 题意:给你一颗树,让你求最小生成树和次小生成树值是否相等. 分析:这个题目关键在于求解次小生成树. 方法是,依次枚举不在最小生成树上的边,然后加入 ...

  8. 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 ...

  9. POJ 1679 The Unique MST:次小生成树【倍增】

    题目链接:http://poj.org/problem?id=1679 题意: 给你一个图,问你这个图的最小生成树是否唯一. 题解: 求这个图的最小生成树和次小生成树.如果相等,则说明不唯一. 次小生 ...

随机推荐

  1. PLSQL存储过程校验身份证

    CREATE OR REPLACE FUNCTION FUN_CHECKIDCARD(PI_AAC002 VARCHAR2)   RETURN VARCHAR2 IS /*************** ...

  2. 什么是USBMini接口

    USB的接口有四种.一种是大头,有A型和B型两种,其中A型最常见,就是我们用的最多的标准的USB接头:一种是小头的,也就是USB Mini,也有A型和B型两种,其中B型应用最多,主要应用于手机.MP4 ...

  3. linux下登陆用户的行为信息—w和who命令详解

    查看用户的操作系统管理员若想知道某一时刻用户的行为,只需要输入命令w 即可,在SHELL终端中输入如下命令: [root@localhost ~]# w 可以看到执行w命令及显示结果. 命令信息含义上 ...

  4. Codeforces Round #250 (Div. 1) D. The Child and Sequence (线段树)

    题目链接:http://codeforces.com/problemset/problem/438/D 给你n个数,m个操作,1操作是查询l到r之间的和,2操作是将l到r之间大于等于x的数xor于x, ...

  5. 【JDBC】百万数据插入

    使用JDBC连接数据库时,如果插入的数据量大,一条一条地插入数据会变得非常缓慢.此时,我们需要用到预处理. 查阅Java开发文档,我们可以看到: 接口 PreparedStatement 表示预编译的 ...

  6. ElasticSearch中文分词(IK)

    ElasticSearch常用的很受欢迎的是IK,这里稍微介绍下安装过程及测试过程.   1.ElasticSearch官方分词 自带的中文分词器很弱,可以体检下: [zsz@VS-zsz ~]$ c ...

  7. Oracle-11g-R2(11.2.0.3.x)RAC Oracle Grid & Database 零宕机方式升级 PSU(自动模式)

    升级环境: 1.源库版本: Grid Infrastructure:11.2.0.3.13 Database:11.2.0.3.13 2.目标库版本: Grid Infrastructure:11.2 ...

  8. 非IE内核浏览器支持activex插件

    之前在一个B/S项目中遇到一个需求,就是客户需要在页面上对报表的布局以及显示内容,进行自定义.最后决定使用activex技术来实现.众所周知,activex是微软搞得,因此只有ie内核的浏览器才能支持 ...

  9. uva11324 The Largest Clique --- 强连通+dp

    给一个有向图G,求一个子图要求当中随意两点至少有一边可达. 问这个子图中最多含多少个顶点. 首先找SCC缩点建图.每一个点的权值就是该点包括点的个数. 要求当中随意两点可达,实际上全部边仅仅能同方向, ...

  10. WCF 新手教程二

    基本知识: [ServiceContract] Attribute 能够有以下Property 的: CallbackContract 设置callback的类型:Duplicate指Service ...