次小生成树(POJ1679/CDOJ1959)
POJ1679
首先求出最小生成树,记录权值之和为MinST。然后枚举添加边(u,v),加上后必形成一个环,找到环上非(u,v)边的权值最大的边,把它删除,计算当前生成树的权值之和,取所有枚举加边后生成树权值之和的最小值

思路:
最小生成树唯一性判断,求次小生成树的val再与最小生成树比较。
1.先用prim算法求出最小生成树。并在其过程中保存加入到MST中的Max[i][j]( i 到 j 路径中的最大边 )
2.对未加入MST的边进行遍历:从MST中去掉i j路径中的最大边,加入未访问边G[i][j],如果得到的生成树的权值和MST的相等,则存在次小生成树的权值=MST的权值和
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f const int N = 1e3+;
int G[N][N]; // graph matrix
int f[N]; // pre node
int vis[N]; // visited node
int dis[N]; // main matrix: the edges(set-u)
int mark[N][N];
int Max[N][N]; // path from i to j max edge
int n,m,best; int prim(int v)
{
int ans=;
vis[v]=;
for(int i=;i<=n;i++)
{
dis[i]=G[v][i];
f[i]=v;
}
dis[v]=;
for(int i=;i<n;i++) // n-1
{
int u=-;
for(int j=;j<=n;j++)
if(!vis[j]&&(u==-||dis[j]<dis[u]))u=j;
if(u==-)break;
vis[u]=;
mark[u][f[u]] = mark[f[u]][u] = ;
ans += dis[u];
for(int j=;j<=n;j++)
{
// compare with visited node record path max edge
if(vis[j])Max[u][j]=Max[j][u]=max(Max[j][f[u]],dis[u]);
if(!vis[j]&&dis[j]>G[u][j])
{
dis[j]=G[u][j];
f[j]=u;
}
}
}
return ans;
} int SMST()
{
int mini=INF;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++) //or for(int j=i+1;j<=n;j++)
{
if(i!=j&&!mark[i][j])
mini = min(mini,best+G[i][j]-Max[i][j]);
}
return mini;
} int main()
{
int x,y,w,T;
scanf("%d",&T);
while(T--)
{
memset( vis, ,sizeof(vis) );
memset( Max, ,sizeof(Max) );
memset( f, ,sizeof(f) );
memset( dis, ,sizeof(dis) );
memset( mark, ,sizeof(mark) );
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
{
if(i==j)G[i][j]==;
else G[i][j]=INF;
}
for(int i=;i<m;i++)
{
scanf("%d%d%d",&x,&y,&w);
G[x][y]=w;
G[y][x]=w;
}
best = prim();
int temp = SMST();
if(temp == best)
printf("Not Unique!\n");
else
printf("%d\n",best);
}
return ;
}
CDOJ 1959
思路:这道题会出现重边,用Kruskal算法处理起来比较方便。(用邻接表方便,邻接矩阵还要考虑同两点之间的多条权值相同的边。)
次小生成树的权值如果等于最小生成树的权值, 其替换边只会是权值相同的边,于是可以把权值相同边放在一起考虑,分别判断全部没有合并时有多少可以合并(cnt1记录的是可以加入集合的边数),边合并边判断有多少可以合并(cnt2记录的是选中一条加入到集合),如果可选的大于构成最小生成树所需要的,那么就存在一种相同的边权可以替换原来的,从而最小生成树不唯一。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 2e5+;
struct Node
{
int u,v;
LL w;
}G[N]; int n,m;
int f[];
int find(int x)
{
return x==f[x]?x:f[x]=find(f[x]);
} bool cmp(Node & a, Node & b)
{
return a.w<b.w;
} void kruskal()
{
int cnt1=;
int cnt2=;
for(int i=;i<=n;i++)f[i]=i;
sort(G,G+m,cmp);
for(int i=;i<m;)
{
int j=i;
while(j<m&&G[j].w==G[i].w)
{
int u = find(G[j].u);
int v = find(G[j].v);
if(u!=v)cnt1++;
j++;
}
j=i;
while(j<m&&G[j].w==G[i].w)
{
int u = find(G[j].u);
int v = find(G[j].v);
if(u!=v){
cnt2++;
f[u]=v;
}
j++;
}
i=j;
if(cnt1>cnt2)break;
}
if( cnt1 > cnt2 ){
printf("zin\n");
}else{
printf("ogisosetsuna\n");
}
} int main()
{
int x,y;
LL w;
cin>>n>>m;
for(int i=;i<m;i++)
{
cin>>x>>y>>w;
G[i].u=x;
G[i].v=y;
G[i].w=w;
}
kruskal();
return ;
}
次小生成树(POJ1679/CDOJ1959)的更多相关文章
- POJ1679 The Unique MST[次小生成树]
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 28673 Accepted: 10239 ...
- POJ1679(次小生成树)
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 36692 Accepted: 13368 ...
- POJ1679(次小生成树)
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 24201 Accepted: 8596 D ...
- POJ1679 The Unique MST【次小生成树】
题意: 判断最小生成树是否唯一. 思路: 首先求出最小生成树,记录现在这个最小生成树上所有的边,然后通过取消其中一条边,找到这两点上其他的边形成一棵新的生成树,求其权值,通过枚举所有可能,通过这些权值 ...
- POJ1679 The Unique MST 【次小生成树】
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 20421 Accepted: 7183 D ...
- 次小生成树(poj1679)
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 20737 Accepted: 7281 D ...
- poj1679次小生成树入门题
次小生成树求法:例如求最小生成树用到了 1.2.4这三条边,总共5条边,那循环3次的时候,每次分别不用1.2.4求得最小生成树的MST,最小的MST即为次小生成树 如下代码maxx即求最小生成树时求得 ...
- POJ1679 The Unique MST —— 次小生成树
题目链接:http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total S ...
- POJ-1679 The Unique MST,次小生成树模板题
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Description Given a connected undirec ...
随机推荐
- Kafka管理工具介绍【转】
Kafka内部提供了许多管理脚本,这些脚本都放在$KAFKA_HOME/bin目录下,而这些类的实现都是放在源码的kafka/core/src/main/scala/kafka/tools/路径下. ...
- Liunx之KVM搭建图形化的WEB
作者:邓聪聪 我们常在Windowns下使用VMware,当然在Liunx中也有这样的软件供我们使用.生产环境的KVM宿主机越来越多,需要对宿主机的状态进行调控.这里用webvirtmgr进行管理.图 ...
- C++类的继承中构造函数和析构函数调用顺序例子
/*当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达派生类次数最多的派生次数最多的类的构造函数为止.简而言之,对象是由“底层向上”开始构造的.因为,构造函数 ...
- boost.asio包装类st_asio_wrapper开发教程(一)
一:什么是st_asio_wrapper它是一个c/s网络编程框架,基于对boost.asio的包装(最低在boost-1.49.0上调试过),目的是快速的构建一个c/s系统: 二:st_asio_w ...
- dynamic详解
一.简介 在通过 dynamic 类型实现的操作中,该类型的作用是绕过编译时类型检查, 改为在运行时解析这些操作. dynamic 类型简化了对 COM API(例如 Office Automatio ...
- strncpy的用法
strncpy是C语言的库函数之一,来自C语言标准库,定义于string.h,函数原型是: char *strncpy(char* dest,char* src,size_t n); 把src所指向的 ...
- mysql备份和bin-log日志
总结]:mysql备份和bin-log日志 备份数据: mysqldump -uroot -p123456 test -l -F '/tmp/test.sql' -l:读锁(只能读取,不能更新) -F ...
- page.isvalid
背景 看到这个标题,想了半天,为啥用的.应该是当初前台要动态增加行这个事情,当初用.net真是用傻了,竟然对html.aspx原理不大清楚,对于html也想着后台生成.真是弱智啊.谈到这里,想到c#这 ...
- $Django Rest Framework-认证组件,权限组件 知识点回顾choices,on_delete
一 小知识点回顾 #orm class UserInfo (models.Model): id = models.AutoField (primary_key=True) name = models. ...
- 讨论HTTP POST 提交数据的几种方式
转自:http://www.cnblogs.com/softidea/p/5745369.html HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS.GET.HEAD.POST.PU ...