次小生成树(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 ...
随机推荐
- 题解-bzoj3569 DZY Loves Chinese II
Problem bzoj 题意概要:给定\(n\)点\(m\)边无向连通图,\(Q\)次询问删除\(k\)条边后是否仍然连通,强制在线 Solution 半年前考到过这类题目(询问删除任意两条边使得图 ...
- 019_Mac实用的图像备份工具
一.mac上有一个非常好用的图像备份工具
- Fiddler对https抓包时,提示"HTTPS decryption is disabled."
安装了fiddlercertmaker.exe 后,对 https://www.baidu.com 进行抓包时,右侧界面提示"HTTPS decryption is disabled.&qu ...
- hibernate映射关系(多对多)
Student与Teacher关系多对多(只建了2个实体类) public class Student { private int id; private String name; private S ...
- Light OJ 1148
题意: 给你N 个人, 每个人说出有多少人和他一队, 不包括他自己, 输出总人数最少值 思路: 排个序, 按照给的数目把人分为一组,就可以得出最少人数 #include<bits/stdc++. ...
- 远程连接阿里云的mysql数据库
第一步 由于mysql版本问题 先尝试打开 sudo vim /etc/mysql/my.cnf 如空,再尝试打开 sudo vim /etc/mysql/mysql.conf.d/mysqld.cn ...
- Poco::Crypto--加解密(AES)
Poco::Crypto--加解密(AES) 1 int main(const std::vector<std::string>& args) 2 { 3 /*TO DO*/ 4 ...
- linux命令排序
sort -k1 -n 第一列按数字正排序 sort -K1 -rn 第一列按数字倒排序
- swift 实践- 09 -- UIImageVIew
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoa ...
- PID控制器开发笔记之四:梯形积分PID控制器的实现
从微积分的基本原理看,积分的实现是在无限细分的情况下进行的矩形加和计算.但是在离散状态下,时间间隔已经足够大,矩形积分在某些时候显得精度要低了一些,于是梯形积分被提出来以提升积分精度. 1.梯形积分基 ...