思路:

Prim:

这道题目中有重边

Prim可以先加一个sec数组来保存重边的次小边,这样不会影响到最小生成树,在算次小生成树时要同时判断次小边(不需判断是否在MST中)

Kruskal:

Kruskal对重边就很友好了,不用考虑

原理是这样的:我们先找最小生成树并用used标记好哪些边是MST的边,然后我们暴力遍历每一条MST边被删去的情况,如果还能生成MST就找出这些MST最小的,这棵MST就是次小生成树

Prim代码:

#include<cmath>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
const int N = 200+5;
const int INF = 0x3f3f3f3f;
using namespace std;
int n,m,p[N],Case = 1;
int mp[N][N],sec[N][N],dis[N],x[N],y[N];
int pre[N];
bool vis[N];
int Max[N][N]; //最大权值边
bool is[N][N]; //是否在MST中 void init(){
int a,b,c;
scanf("%d%d",&n,&m);
memset(mp,INF,sizeof(mp));
memset(sec,INF,sizeof(sec));
for(int i = 1;i <= m;i++){
scanf("%d%d%d",&a,&b,&c);
if(c < mp[a][b]){
sec[a][b] = sec[b][a] = min(mp[a][b],sec[a][b]); //保存次小边
mp[a][b] = mp[b][a] = c;
}
else{
sec[a][b] = sec[b][a] = min(c,sec[a][b]);
}
}
memset(vis,false,sizeof(vis));
vis[1] = true;
for(int i = 2;i <= n;i++){
dis[i] = mp[i][1];
pre[i] = 1;
}
}
void Prim(){
int mincost = 0;
memset(Max,0,sizeof(Max));
memset(is,false,sizeof(is));
for(int i = 1;i <= n - 1;i++){
int MIN = INF;
int point = -1;
for(int j = 1;j <= n;j++){
if(!vis[j] && dis[j] < MIN){
MIN = dis[j];
point = j;
}
}
if(point == -1){
printf("Case #%d : No way\n",Case++);
return;
}
vis[point] = true;
mincost += MIN;
is[point][pre[point]] = is[pre[point]][point] = true;
for(int j = 1;j <= n;j++){
if(vis[j] && j != point){
Max[j][point] = Max[point][j] = max(Max[pre[point]][j],dis[point]);
}
if(!vis[j] && dis[j] > mp[j][point]){
pre[j] = point;
dis[j] = mp[j][point];
}
}
}
int seccost = INF,flag = 0;
for(int i = 1;i <= n;i++){
for(int j = 1;j < i;j++){
if(mp[i][j] != INF && !is[i][j]){
flag = 1;
seccost = min(seccost,mincost - Max[i][j] + mp[i][j]);
}
if(sec[i][j] != INF){
flag = 1;
seccost = min(seccost,mincost - Max[i][j] + sec[i][j]);
}
}
}
if(!flag) printf("Case #%d : No second way\n",Case++);
else printf("Case #%d : %d\n",Case++,seccost);
}
int main() {
int T;
scanf("%d",&T);
while(T--){
init();
Prim();
}
return 0;
}

Kruskal代码:

#include<cmath>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
const int N = 200+5;
const int INF = 0x3f3f3f3f;
using namespace std;
struct edge{
int u,v,w;
}e[N];
bool cmp(edge a,edge b){
return a.w < b.w;
}
int f[N],used[N];
int Case = 1;
int Find(int x){
return f[x] == x? x : f[x] = Find(f[x]);
}
void Kruskal(){
int n,m,a,b,c;
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;i++){
scanf("%d%d%d",&a,&b,&c);
e[i].u = a;
e[i].v = b;
e[i].w = c;
}
sort(e+1,e+m+1,cmp);
for(int i = 0;i <= n;i++) f[i] = i;
int cnt = 0,tot = 0;
for(int i = 1;i <= m;i++){
int fx = Find(e[i].u);
int fy = Find(e[i].v);
if(fx != fy){
f[fx] = fy;
cnt++;
used[tot++] = i;
}
if(cnt == n - 1) break;
}
if(cnt < n - 1){
printf("Case #%d : No way\n",Case++);
return;
}
//次小生成树
int seccost = INF;
for(int i = 0;i < tot;i++){
for(int j = 0;j <= n;j++) f[j] = j;
int num = 0,cost = 0;
for(int j = 1;j <= m;j++){
if(j == used[i]) continue; //删边
int fx = Find(e[j].u);
int fy = Find(e[j].v);
if(fx != fy){
f[fx] = fy;
num++;
cost += e[j].w;
}
if(num == n - 1) break;
}
if(num == n-1) seccost = min(seccost,cost);
}
if(seccost == INF) printf("Case #%d : No second way\n",Case++);
else printf("Case #%d : %d\n",Case++,seccost);
}
int main() {
int T;
scanf("%d",&T);
while(T--){
Kruskal();
}
return 0;
}

UVA 10462 Is There A Second Way Left?(次小生成树&Prim&Kruskal)题解的更多相关文章

  1. UVA 10462 Is There A Second Way Left? 次小生成树

    模板题 #include <iostream> #include <algorithm> #include <cstdio> #include <cstdli ...

  2. UVA 10462 Is There A Second Way Left? (次小生成树+kruskal)

    题目大意: Nasa应邻居们的要求,决定用一个网络把大家链接在一起.给出v个点,e条可行路线,每条路线分别是x连接到y需要花费w. 1:如果不存在最小生成树,输出“No way”. 2:如果不存在次小 ...

  3. UVA - 10462-Is There A Second Way Left? Kruskal求次小生成树

    UVA - 10462 题意: 求次小生成树的模板题,这道题因为有重边的存在,所以用kruskal求比较好. #include <iostream> #include <cstdio ...

  4. UVA 10462 —— Is There A Second Way Left?——————【最小生成树、kruskal、重边】

    Nasa, being the most talented programmer of his time, can’t think things to be so simple. Recently a ...

  5. UVA - 10462 Is There A Second Way Left?

    题意: 给你一张无向图,让你判断三种情况:1.不是连通图(无法形成生成树)2.只能生成唯一的生成树 3.能生成的生成树不唯一(有次小生成树),这种情况要求出次小生成树的边权值和. 思路: 比较常见的次 ...

  6. UVA 10600 ACM Contest and Blackout 次小生成树

    又是求次小生成树,就是求出最小生成树,然后枚举不在最小生成树上的每条边,求出包含着条边的最小生成树,然后取一个最小的 #include <iostream> #include <al ...

  7. 【UVA 10600】 ACM Contest and Blackout(最小生成树和次小生成树)

    [题意] n个点,m条边,求最小生成树的值和次小生成树的值. InputThe Input starts with the number of test cases, T (1 < T < ...

  8. [ An Ac a Day ^_^ ] [kuangbin带你飞]专题八 生成树 UVA 10600 ACM Contest and Blackout 最小生成树+次小生成树

    题意就是求最小生成树和次小生成树 #include<cstdio> #include<iostream> #include<algorithm> #include& ...

  9. Qin Shi Huang's National Road System UVA - 1494(次小生成树)

    秦始皇统一中国之后要在全国修公路连接各个城市,皇帝只想修成最小生成树(距离最小,不考虑人力),一个道士说自己可以不花人力物力修一条路,经过两方妥协,选择max(两个城市人口/(生成树长度-这条路的长度 ...

随机推荐

  1. Intellij Idea常用配置设置

    1.配置Intellij Idea的配置文件从默认c盘转移到其他盘符 找到Intellij idea的安装文件,在bin目录下找到idea.properties配置文件,如下把Idea的配置文件夹和I ...

  2. 【python+opencv】轮廓发现

    python+opencv---轮廓发现 轮廓发现---是基于图像边缘提取的基础寻找对象轮廓的方法, 所有边缘提取的阈值选定会影响最终轮廓发现的结果. 介绍两种API使用: -cv.findConto ...

  3. dedecms用keyword标签调用含有某一关键词的文章

    前面我们探讨了调用{dede:likewords}为dedecms添加相关搜索词,如果要调用含有某一关键词的文章可以实现吗?比如ytkah的网站有很多文章中含有“微信”的词,那么想在网站首页.频道页. ...

  4. VUX

    1.mapState 2.mapGetters 3. 4. 当你的操作行为中含有异步操作,比如向后台发送请求获取数据,就需要使用action的dispatch去完成.其他使用commit即可. 举个例 ...

  5. OC 手势可能出现的问题

    oc手势有分別是 Tap(点一下).Pinch(二指往內或往外拨动).Rotation(旋转).Swipe(滑动,快速移动).Pan (拖移,慢速移动)以及 LongPress(长按). UITapG ...

  6. vue中使用better-scroll实现滑动效果

    1.安装:npm install better-scroll 2.引入:import BetterScrol from "better-scroll"; 1.滚动效果 better ...

  7. jQuery内部原理和实现方式浅析

    这篇文章主要介绍了jQuery内部原理和实现方式浅析,本文试图从整体来阐述一下jQuery的内部实现,需要的朋友可以参考下 这段时间在学习研究jQuery源码,受益于jQuery日益发展强大,研究jQ ...

  8. [dt]世纪历史长河年代表

    年代口诀 夏商与西周, 东周分两段, 春秋和战国, 一统秦两汉, 三分魏蜀吴, 二晋前后延, 南北朝并列, 隋唐五代传, 宋元明清后, 皇朝至此完. 中国历史长河年代表 参考: 中国历史朝代顺序表.年 ...

  9. Google面试题[一]

    谷歌是不少IT人都想去的企业,那么在进入公司前,少不了面试笔试的测试.那么这里我们就总结了如下谷歌笔试题,并提供了一些参考答案.希望对您有用. 谷歌笔试题:判断一个自然数是否是某个数的平方.当然不能使 ...

  10. nodejs+express的(前端跨域请求)

    1.后端代码 var dp = 456; var back = 'callback(\{\dp\ : \ ' + dp + '\ }\)'; res.send(back); 2.前端代码 <sc ...