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

修路方案

时间限制: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
Prim+次小生成树。
次小生成树的两种算法:算法1、step 1.  先用prim求出最小生成树T.         在prim的同一时候。用一个矩阵max[u][v] 记录 在T中连结随意两点u,v的唯一的         路中权值最大的那条边的权值. (注意这里).         这是非常easy做到的。由于prim是每次增加一个结点s, 而设已经标号了的结点         集合为W, 则W中全部的结点到s的路中的最大权值的边就是当前增加的这条边.         step 1 用时 O(V^2).     step 2.  枚举全部不在T中的边uv, 增加边uv则必定替换权为max[u][v]的边。

算法2、先用prim求出最小生成树T。           枚举T中的每一条边,把它删除,求剩下的图的最小生成树。

选全部枚举得到的生成树中的最小的那一个。
AC码:
#include<stdio.h>
#include<string.h>
#define INF 99999999
int G[505][505],visit[505],lowcost[505];
int repair[505][505],pre[505],f[505][505];
int main()
{
	int T,v,e,a,b,cost,MinTree,ans,i,j,k,min;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&v,&e);
		//memset(G,INF,sizeof(G));   // 对矩阵G赋值,仅仅能赋为0或-1,假设赋为INF,提交不成功
		for(i=0;i<=v;i++)
		{
			for(j=0;j<=v;j++)
				G[i][j]=INF;
		}
		memset(repair,0,sizeof(repair));

		for(i=0;i<e;i++)
		{
			scanf("%d%d%d",&a,&b,&cost);
			G[a][b]=G[b][a]=cost;
			// 把该边初始为可修状态
			repair[a][b]=repair[b][a]=1;  // repair:修
		}

		// Prim算法生成最小树
		memset(visit,0,sizeof(visit));
		memset(f,0,sizeof(f));
		for(i=1;i<=v;i++)
		{
			lowcost[i]=G[1][i];      // 初始化lowcost的值
			pre[i]=1;                // 辅助数组
		}
		visit[1]=1;
		k=1;
		MinTree=0;
		for(i=1;i<=v;i++)
		{
			min=INF;
			for(j=1;j<=v;j++)
			{
				if(!visit[j]&&min>lowcost[j])
				{
					min=lowcost[j];
					k=j;
				}
			}
			if(min==INF)
				break;
			repair[pre[k]][k]=repair[k][pre[k]]=0;
			MinTree+=min;
			visit[k]=1;
			for(j=1;j<=v;j++)
			{
				if(visit[j])
					f[k][j]=f[j][k]=f[j][pre[k]]>G[pre[k]][k]?f[j][pre[k]]:G[pre[k]][k];
				if(!visit[j]&&G[k][j]<lowcost[j])
				{
					lowcost[j]=G[k][j];
					pre[j]=k;
				}
			}
		}

		// 再求次小生成树
		ans=INF;
		for(i=1;i<=v;i++)
		{
			for(j=1;j<=v;j++)
			{
				if(repair[i][j])
					ans=ans<(MinTree-f[i][j]+G[i][j])?ans:(MinTree-f[i][j]+G[i][j]);
			}
		}
		if(ans==MinTree)
			printf("Yes\n");
		else
			printf("No\n");
	}
	return 0;
}

版权声明:本文博主原创文章,博客,未经同意不得转载。

时间: 2024-08-01 22:47:28

NYOJ 118 路方案(第二小的跨越)的相关文章

NYOJ 118 修路方案

修路方案 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描述 南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路. 现在已经知道哪些城市之间可以修路,如果修路,花费是多少. 现在,军师小工已经找到了一种修路的方案,能够使各个城市都联通起来,而且花费最少. 但是,南将军说,这个修路方案所拼成的图案很不吉利,想让小工计算一下是否存在另外一种方案花费和刚才的方案一样,现在你来帮小工写一个程序算一下吧. 输入 第一行输

codevs 1700 施工方案第二季

1700 施工方案第二季 2012年市队选拔赛北京 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description c国边防军在边境某处的阵地是由n个地堡组成的.工兵连受命来到阵地要进行两期施工. 第一期的任务是挖掘暗道让所有地堡互联互通.现已勘测设计了m条互不相交的暗道挖掘方案,如果这m条暗道都实施挖掘,肯定能达到互联互通的目的.事实上,适当选择其中n-1个方案挖掘,就能实现互联互通,即从每个地堡出发都能到达其他任何一个地堡(允许经过别

Python之路【第二篇】:Python基础(一)

Python之路[第二篇]:Python基础(一) 入门知识拾遗 一.作用域 对于变量的作用域,执行声明并在内存中存在,该变量就可以在下面的代码中使用. 1 2 3 if 1==1:     name = 'wupeiqi' print  name 下面的结论对吗? 外层变量,可以被内层变量使用 内层变量,无法被外层变量使用 二.三元运算 1 result = 值1 if 条件 else 值2 如果条件为真:result = 值1如果条件为假:result = 值2 三.进制 二进制,01 八进

NYOJ 469 擅长排列的小明 II

擅长排列的小明 II 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 小明十分聪明,而且十分擅长排列计算. 有一天小明心血来潮想考考你,他给了你一个正整数n,序列1,2,3,4,5......n满足以下情况的排列: 1.第一个数必须是1 2.相邻两个数之差不大于2 你的任务是给出排列的种数. 输入 多组数据.每组数据中输入一个正整数n(n<=55). 输出 输出种数. 样例输入 4 样例输出 4 来源 Ural 上传者 李文鑫 解题:俺找规律才找出来的,开始写了个暴

HDU 2561 第二小整数

第二小整数 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10766    Accepted Submission(s): 6548 Problem Description 求n个整数中倒数第二小的数.每一个整数都独立看成一个数,比如,有三个数分别是1,1,3,那么,第二小的数就是1. Input 输入包含多组测试数据.输入的第一行是一

第二小整数

Problem Description 求n个整数中倒数第二小的数.每一个整数都独立看成一个数,比如,有三个数分别是1,1,3,那么,第二小的数就是1. Input 输入包含多组测试数据.输入的第一行是一个整数C,表示有C测试数据:每组测试数据的第一行是一个整数n,表示本组测试数据有n个整数(2<=n<=10),接着一行是 n个整数 (每个数均小于100); Output 请为每组测试数据输出第二小的整数,每组输出占一行. Sample Input 2 2 1 2 3 1 1 3 Sample

找到n个元素中的第二小元素

算法导论中的一道习题: 证明: 在最坏情况下,找到n个元素中的第二小的元素需要n+ceil(lgn)-2次比较.(提示:可以同时找到最小元素,ceil表示向上取整) 思路: 找到最小元素需要n-1次比较.采用两两结合比较的方法.如果n为奇数,则取第一个元素为临时最小元素min,其它两两结合比较,形成一个类似树的比较过程.如果n为偶数,则直接进行两两结合比较,根节点即为最小元素. 接下来查找第二小元素,需要ceil(lgn)-1次比较.考虑:第二小元素一定和第一小元素进行了比较,所以可以直接在比较

HDOJ/HDU 2561 第二小整数(水题~排序~)

Problem Description 求n个整数中倒数第二小的数. 每一个整数都独立看成一个数,比如,有三个数分别是1,1,3,那么,第二小的数就是1. Input 输入包含多组测试数据. 输入的第一行是一个整数C,表示有C测试数据: 每组测试数据的第一行是一个整数n,表示本组测试数据有n个整数(2<=n<=10),接着一行是 n个整数 (每个数均小于100); Output 请为每组测试数据输出第二小的整数,每组输出占一行. Sample Input 2 2 1 2 3 1 1 3 Sam

找出该树中第二小的值--思路及算法实现

在二叉树中最重要的操作莫过于遍历,即按照某一顺序访问树中的所有节点.二叉树的前序遍历.中序遍历.后序遍历都有递归和循环两种不同的实现方法.每种遍历的递归实现都比循环实现要简洁很多.下面分享一个关于二叉树遍历到笔试题: 给定一棵完全二叉树,即树中的每一个节点有2个子节点或者没有子节点,每一个节点的值小于等于它的子节点的值.请找出该树中第二小的值.如果没有第二小的值,请给出-1: 解题思路:画图举例解决问题,如下图所示,根节点是1,每一个节点的值小于等于它的子节点的值,访问根节点后再先后访问左子树和