------------只要够努力,人生最坏的结局不过是大器晚成!!!

链接:https://www.nowcoder.net/acm/contest/76/B
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 65536K,其他语言131072K
64bit IO Format: %lld

题目描述

随着如今社会的不断变化,交通问题也变得越来越重要,所以市长决定建设一些公路来方便各个城市之间的贸易和交易。虽然市长的想法很好,但是他也遇到了一般人也经常头疼的问题,那就是手头的经费有限……在规划过程中,设计师们已经预算出部分城市之间建设公路的经费需求。现在市长想知道,它能不能将他的m个城市在有限的经费内实现公路交通。如果可以的话,输出Yes,否则输出No(两个城市不一定要直接的公路相连,间接公路到达也可以。)

输入描述:

测试输入包含多条测试数据
每个测试数据的第1行分别给出可用的经费c(<1000000),道路数目n(n<10000),以及城市数目m(<100)。
接下来的n行给出建立公路的成本信息,每行给出三个整数,分别是相连的两个城市v1、v2(0<v1,v2<=m)以及建设公路所需的成本h(h<100)。

输出描述:

对每个测试用例,输出Yes或No。
示例1

输入

20 10 5
1 2 6
1 3 3
1 4 4
1 5 5
2 3 7
2 4 7
2 5 8
3 4 6
3 5 9
4 5 2

输出

Yes
示例2

输入

10 2 2
1 2 5
1 2 15

输出

Yes

备注:

两个城市之间可能存在多条线路

Kruskal算法:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef struct Edge{
	int x;
	int y;
	int w;
}Edge;
Edge edge[10005];
int n, m;  //n道路数,m城市数 
int f[105];
bool cmp(Edge a, Edge b){
	return a.w < b.w;
}  
int find(int x){
	if(f[x] == -1) 
		return x;
	else{
		return find(f[x]);
	}
}
/*
压缩一下的并查集 
int find(int x){ 
    int root = x; 
    while(root != par[root]) root = par[root]; 
    while(x != root){ 
        int t = par[x]; 
        par[x] = root; 
        x = t; 
    } 
    return root; 
} 
   
void unite(int x, int y){ 
    x = find(x); 
    y = find(y); 
    if(Rank[x] < Rank[y]){ 
        par[x] = y; 
    } 
    else{ 
        par[y] = x; 
        if(Rank[x] == Rank[y]) Rank[x]++; 
    } 
}
*/ 

int Kruskal(){
	int ans = 0, cnt = 0;
	sort(edge, edge + n, cmp);
	for(int i = 0; i < n; i++){
		int x, y, w;
		x = edge[i].x;
		y = edge[i].y;
		w = edge[i].w;
		if(find(x) != find(y)){
			ans += w;
			f[x] = y; //unite(x,y); 
			cnt++;
		}
		if(cnt == m - 1) //m个城市只需 m - 1条道路就可以了 
			break;
	}
	if(cnt < m - 1){
		return -1;
	}
	return ans;
}
int main(){
	int cost, x, y, w;
	while(scanf("%d%d%d", &cost, &n, &m) == 3){
		memset(edge, 0, sizeof(edge));
		memset(f, -1, sizeof(f));
		for(int i = 0; i < n; i++){
			scanf("%d%d%d", &x, &y, &w);
			edge[i].x = x;
			edge[i].y = y;
			edge[i].w = w;
		}
		int ans = Kruskal();
		if(ans <= cost){
			printf("Yes\n");
		}
		else{
			printf("No\n");
		}
	}
	return 0;
}

Prim算法:(超内存)

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 10005
bool visit[MAXN]; 		//标记数字是否放入一个集合 
int lowc[MAXN];   		//维护的最低代价数组	
int cost[MAXN][MAXN];   //边的的权值 

int Prim(int n){
	int ans = 0;
	visit[1] = true;
	for(int i = 2; i <= n; i++){
		lowc[i] = cost[1][i];
	}
	for(int i = 1; i < n; i++){  //将剩余的n-1个点放入visit  
		int minc = INF;
		int p = 0;
		for(int j = 2; j <= n; j++){  //查找一个没有放入visit的且权值最小的顶点 
			if(!visit[j] && minc > lowc[j]){
				minc = lowc[j]; 
				p = j;	
			}
		}
		if(minc == INF) //这是一个不连通图,所以无最小生成树 
			return -1;
		ans += minc;
		visit[p] = true;
		for(int i = 2; i <= n; i++){ //更新维护顶点到visit集合的最小消耗 
			if(lowc[i] > cost[p][i]){
				lowc[i] = cost[p][i];
			}
		}
	}
	return ans;
}
int main(){
	int n, m; //顶点,边数 
	int allm = 0;
	while(scanf("%d%d%d", &allm, &n, &m) == 3){
		memset(cost, INF, sizeof(cost));
		int u, v, w;
		for(int i = 1; i <= m; i++){
			scanf("%d%d%d", &u, &v, &w);
			if(cost[u][v] > w){
				cost[u][v] = w;
				cost[v][u] = w;	
			}
		}
		int ans = Prim(n);
//		cout << ans << "xiaofei" <<  endl;
		if(allm >= ans){
			printf("Yes\n");
		}
		else{
			printf("No\n");
		}
	}
	return 0;
}
 

  

posted on 2018-02-11 18:17  ystraw  阅读(243)  评论(0编辑  收藏  举报

不经一番切孤寒,怎得梅花扑鼻香