次小生成树(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 ...
随机推荐
- Python os.walk文件遍历用法【转】
python中os.walk是一个简单易用的文件.目录遍历器,可以帮助我们高效的处理文件.目录方面的事情. 1.载入 要使用os.walk,首先要载入该函数 可以使用以下两种方法 import os ...
- HTTP协议03-http特点及请求方式
无状态: HTTP是一种不保存状态,既无状态协议.HTTP自身不对请求和响应之间的通信状态进行保存,也就是说不做持久化处理.这是为了更快处理大量事务,确保协议的可伸缩性. 随着web的不断发展,无状态 ...
- CLR via C#关于泛型(Generics )的摘录
泛型,是CLR和编程语言提供的一种特殊机制,它支持另一种形式的代码重用,即“算法重用”. 简单的说,开发人员先定义好一个算法,比如排序.搜索.交换.比较或者转换等.但是,定义算法的开发人员并不设改算法 ...
- svn更新出现冲突的解决方法
Conflict discovered in '/Users/apple/EtaxiAppServer/common/src/com/yaotaxi/db/MongoDBHelper.java'. S ...
- Linq与Lambda常用查询语法
1.查询全部 2.按条件查询全部 3.去除重复 4.连接查询 between and 5.排序 6.分组
- 如何安装和配置RabbitMQ
今天开始一个小小的练习,学习一下安装和配置RabbitMQ,为什么要学它,因为WCF可以完全兼容和使用RabbitMQ了.我们新的大数据系统需要使用消息队列,所以就开始研究一下,把它重新封装一下,更便 ...
- Ex 2_5 求解递推式..._第三次作业
- Oracle12c 性能优化攻略:攻略1-3: 匹配表类型与业务需求
注:目录表 <Oracle12c 性能优化攻略:攻略目录表> 问题描述 你刚开始使用oracle数据库,并且学习了一些关于可用的各种表类型的知识.例如:可以在堆组织表.索引组织表等之间支出 ...
- ES6学习路上的小学生,promise处理异步操作,简易原始起步之用。先能用,再深究!
ES6的promise对象,让我们更容易的处理这样的需求:执行完一个方法以后,再去执行下一个方法. 理解尚浅之时,先用于项目之中. var promise1 = new Promise(functio ...
- iframe内容自适应高度
一直觉得要用JS才能实现iframe高度的自适应,其实CSS也可以,而且实现的更好,只是需要给包裹iframe的DIV设置个高度,然后让irame高度设置成100%就可以自适应了. 完美版Iframe ...