修路方案

时间限制:3000 ms  |  内存限制:65535 KB
难度:5
 
描述

南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路。

现在已经知道哪些城市之间可以修路,如果修路,花费是多少。

现在,军师小工已经找到了一种修路的方案,能够使各个城市都联通起来,而且花费最少。

但是,南将军说,这个修路方案所拼成的图案很不吉利,想让小工计算一下是否存在另外一种方案花费和刚才的方案一样,现在你来帮小工写一个程序算一下吧。

 
输入
第一行输入一个整数T(1<T<20),表示测试数据的组数
每组测试数据的第一行是两个整数V,E,(3<V<500,10<E<200000)分别表示城市的个数和城市之间路的条数。数据保证所有的城市都有路相连。
随后的E行,每行有三个数字A B L,表示A号城市与B号城市之间修路花费为L。
输出
对于每组测试数据输出Yes或No(如果存在两种以上的最小花费方案则输出Yes,如果最小花费的方案只有一种,则输出No)
样例输入
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
样例输出
No
Yes
来源
POJ题目改编
上传者
张云聪

解题:次小生成树,搞了好久,好多文档看不懂啊。。。只好学点奇葩的东西,走点旁门左道了。。。。。弱菜有弱菜的学习方法。。。

这是什么算法。。。?好吧。。。偷学于豆丁上一篇文章<<A-star和第k短路和次小生成树和Yen和MPS寻路算法>>

首先求出原图的最小生成树,记录权值之和为Minst.枚举添加每条不在最小生成树上的边<u,v>,加上以后一定会形成一个环,找到环上权值第二大的边(即除<u,v>外最大的边)把它删除掉,计算当前生成树的权值之和。取所有枚举修改的生成树权值之和的最小值,就是次小生成树。具体实现时,更简单的方法是从每个节点i遍历整个最小生成树,定义F[j]为从i到j的路径上最大边的权值。遍历图求出F[j]的值,然后对于添加每条不在最小生成树中的边<i,j>,新的生成树权值之和就是Minst-w<i,j>-F[j],记录其最小值,则为次小生成树。该算法的时间复杂度为O(n^2+m)。由于只用求一次最小生成树,可以用最简单的Prim算法,时间复杂度为O(n^2)。算法的瓶颈不在于最小生成树,而在于O(n^2+m)的枚举加边修改,所以用更好的最小生成树算法是没有必要的。


 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <climits>
#include <algorithm>
#include <cmath>
#define LL long long
#define INF 0x3f3f3f
using namespace std;
struct arc {
int u,v,w;
} e[];
int mp[][],d[],pre[],uf[];
int n,m;
bool vis[];
bool cmp(const arc &x,const arc &y){
return x.w < y.w;
}
int findF(int x){
if(x != uf[x])
uf[x] = findF(uf[x]);
return uf[x];
}
int kruskal(){
int i,j,ans = ;
for(i = ; i <= n; i++){
uf[i] = i;
pre[i] = -;
}
memset(vis,false,true);
for(i = ; i < m; i++){
int x = findF(e[i].u);
int y = findF(e[i].v);
if(x != y){
uf[x] = y;
ans += e[i].w;
pre[e[i].v] = e[i].u;
vis[i] = true;
}
}
return ans;
}
int main() {
int ks,i,j,Minst,mx,u,v;
bool flag;
scanf("%d",&ks);
while(ks--) {
scanf("%d%d",&n,&m);
for(i = ; i < m; i++) {
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
if(e[i].u > e[i].v) swap(e[i].u,e[i].v);
mp[e[i].u][e[i].v] = mp[e[i].v][e[i].u] = e[i].w;
}
sort(e,e+m,cmp);
Minst = kruskal();
flag = false;
for(i = ; i < m; i++){
if(!vis[i]){
mx = ;
u = e[i].u;
v = e[i].v;
while(pre[v] != u && pre[v] != -){
if(mp[v][pre[v]] > mx) mx = mp[v][pre[v]];
v = pre[v];
}
if(mx == e[i].w){
flag = true;break;
}
}
}
flag?puts("Yes"):puts("No");
}
return ;
}
 别人写的Prim算法版的次小生成树
 #include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define maxN 510
#define MAX 0x0fffffff
#define MIN -0x0fffffff
int N,M,map[maxN][maxN],dis[maxN],maxlen[maxN][maxN],pre[maxN];
bool vis[maxN];
int prim() {
int i,j,k,minn,pr;
memset(vis,false,sizeof(vis));
for(i=; i<=N; i++) {
dis[i]=map[][i];
pre[i]=;
}
vis[]=true;
for(j=; j<N; j++) {
minn = MAX;
for(i=; i <= N; i++)
if(!vis[i] && dis[i]<minn) {
minn=dis[k=i];
}
pr = pre[k];
maxlen[k][pr] = maxlen[pr][k] = map[k][pr];
for(i = ; i <= N; i++)
if(vis[i])
maxlen[i][k]=maxlen[k][i]=max(maxlen[i][pr],maxlen[pr][k]);
vis[k]=true;
for(i=; i<=N; i++)
if(!vis[i]&&dis[i]>map[k][i]) {
dis[i]=map[i][k];
pre[i]=k;
}
}
for(i=; i < N; i++)
for(j = i+; j <= N; j++)
if(pre[i] == j|| pre[j] == i) continue;
else if(maxlen[i][j] == map[i][j]) return ;
return ;
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
int u,v,w;
scanf("%d%d",&N,&M);
for(int i = ; i <= N; i++)
for(int j=; j <= N; j++) {
map[i][j] = MAX;
maxlen[i][j] = MIN;
}
for(int i = ; i < M; i++) {
scanf("%d%d%d",&u,&v,&w);
map[u][v]=map[v][u]=w;
}
if(prim())printf("Yes\n");
else printf("No\n");
}
return ;
}

 

NYOJ 118 修路方案的更多相关文章

  1. nyoj 118 修路方案(最小生成树删边求多个最小生成树)

    修路方案 时间限制:3000 ms  |  内存限制:65535 KB 难度:5   描述 南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修 ...

  2. NYOJ 118 路方案(第二小的跨越)

    修路方案 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描写叙述 南将军率领着很多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N.因为交通不太便利,南将军准备修 ...

  3. 修路方案(nyoj)

    算法:次小生成树 描述 南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路. 现在已经知道哪些城市之间可以修路,如果修路,花费是多少. 现在 ...

  4. Nyoj 修路方案(次小生成树)

    描述 南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路. 现在已经知道哪些城市之间可以修路,如果修路,花费是多少. 现在,军师小工已经找到 ...

  5. nyoj_118:修路方案(次小生成树)

    题目链接 题意,判断次小生成树与最小生成树的权值和是否相等. 豆丁文档-- A-star和第k短路和次小生成树和Yen和MPS寻路算法 法一: 先求一次最小生成树,将这棵树上的边加入一个向量中,再判断 ...

  6. 修路方案 Kruskal 之 次小生成树

    次小生成树 : Kruskal 是先求出来  最小生成树 , 并且记录下来所用到的的边 , 然后再求每次都 去掉最小生成树中的一个边 , 这样求最小生成树 , 然后看能不能得到 和原来最小生成树一样的 ...

  7. nyoj--118--修路方案(次小生成树)

    修路方案 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描述 南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路. ...

  8. DP:Making the Grade(POJ 3666)

     聪明的修路方案 题目大意:就是农夫要修一条路,现在要求这条路要么就是上升的,要么就是下降的,总代价为∑|a[i]-b[i]|,求代价最低的修路方案, (0 ≤ β≤ 1,000,000,000) , ...

  9. 最小生成树模板题 hpu 积分赛 Vegetable and Road again

    问题 H: Vegetable and Road again 时间限制: 1 Sec 内存限制: 128 MB 提交: 19 解决: 8 题目描述 修路的方案终于确定了.市政府要求任意两个公园之间都必 ...

随机推荐

  1. jQuery测试及解析

    解析:下标从0开始 解析:最大119  解析:鼠标移过mouseover  解析:  var   变量值=变量名

  2. Java 实现Excel表数据的读取和写入 以及过程中可能遇到的问题

    问题1:Unable to recognize OLE stream 格式的问题要可能是因为给的数据是2010年的数据表后缀为.xlsx,要先转化成2003版的后缀为.xls 问题2: Warning ...

  3. Android 麦克风录音带音量大小动态显示的圆形自定义View

    1.所谓无图无真相,先上效果图.我们要实现的就是中间那个录音的按钮,周边会显示一圈音量大小的波形 2.VolumCircleBar继承自View,我们进行了自定义,代码如下 package com.r ...

  4. rm和mv和dirname和查看文件的命令

    rm -f -i -r ############################ mv -f -i -u 比较新旧 ########################### basename   获取文 ...

  5. github入门之创建仓库--3

    1.登陆到github,点击加号中的New repository 2.设置仓库信息 *注: ------Description:添加仓库说明,不是必填项 ------Public.Private:选择 ...

  6. SQL2005中使用backup、restore来备份和恢复数据库

    在SQL2005数据库中利用SQL语句进行数据备份与还原: 备份backup:backup database 数据库名称 tO disk = 备份路径例:BACKUP DATABASE test TO ...

  7. 如何找到SAP Cloud for Customer标准培训和认证方面的信息

    有一些朋友询问我如何在SAP官网上找到和SAP Cloud for Customer相关的标准培训信息,我这里把步骤写出来: 登录SAP官网https://training.sap.com 输入和Cl ...

  8. 如何让Spring MVC显示自定义的404 Not Found页面

    不知道大家对千篇一律的404 Not Found的错误页面是否感到腻歪了?其实通过很简单的配置就能够让Spring MVC显示您自定义的404 Not Found错误页面. 在WEB-INF的web. ...

  9. App Store上的开源应用汇总

    以下是互联网上主要的开源iOS应用的列表,在学习的时候,多看看完成的功能代码可以给我们带来很多经验,但是除了Apple官方提供的Sample Code之外,我们很难找到优质的开源项目代码,所以我搜集了 ...

  10. MATLAB——解数独

    数独 数独是一种逻辑游戏,玩家需要根据9x9盘面的已知数字,推理出剩余所有空格的数字,并满足每一行.每一列和每个粗线宫(3x3)内均含1~9,不重复. MATLAB中有关函数 M = dlmread( ...