Pku2831 Can We Build This One?(次小生成树)

题意:
某国计划修建若干高速公路,用来连接国内N个城市,经过一番细致的考察后,政府迁出了M条待建的公路 

每条公路用三个整数(x,y,z)来,即城市X与城市Y之间可以修一条高速公路,需要Z的花费。出于节约,政府希望从这些公路出选一些出来修建,使总开支最小。并保证建造后任意两个城市之间都可以直接或间接相连。但往往只考虑费用并不能得到最有价值的方案,例如城市A与城市B之间活动较频繁为了方便这两个城市间交通运输,应修建一条AB间直达的高速公路。于是政府考试将某些公路的建造开支降低 ,使得修筑这条公路后,仍然可以得到一个总开支最低(甚至比原来更低)方案,你的任务就是判断这样的计划可不可行。

思路:mx[i][j]记录顶点i到顶点j路径上最长的边,如果修改的费用c大于最长边,则不可以修改。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1005;
int n,m,k;
int G[maxn][maxn],mx[maxn][maxn];

struct Edge{
	int u;
	int v;
	int w;
	bool operator < (const Edge &e) const {
		return w<e.w;
	}
}edge[maxn*100];

int e;

void init(){
	e=1;
	memset(G,INF,sizeof(G));
	memset(mx,0,sizeof(mx));
}

void addEdge(int u,int v,int w){
	edge[e].u=u;
	edge[e].v=v;
	edge[e].w=w;
	e++;
}

int pre[maxn],low[maxn],vis[maxn];

void Prim(){
	memset(vis,0,sizeof(vis));
	int pos=1;
	for(int i=1;i<=n;i++) low[i]=G[pos][i];
	low[pos]=0,vis[pos]=1,pre[pos]=1;
	for(int i=1;i<=n;i++){
		int min=INF;
		for(int j=1;j<=n;j++){
			if(!vis[j]&&low[j]<min){
				min=low[pos=j];
			}
		}
		for(int j=1;j<=n;j++){
			if(vis[j]){
				mx[pos][j]=max(mx[j][pre[pos]],low[pos]);
				mx[j][pos]=mx[pos][j];
			}
		}
		vis[pos]=1;
		for(int j=1;j<=n;j++){
			if(!vis[j]&&low[j]>G[pos][j]){
				low[j]=G[pos][j];
				pre[j]=pos;
			}
		}
	}
}

int main(){
#ifndef ONLINE_JUDGE
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);
#endif
	while(~scanf("%d%d%d",&n,&m,&k)){
		init();
		for(int i=1;i<=n;i++) G[i][i]=0;
		int u,v,w;
		while(m--){
			scanf("%d%d%d",&u,&v,&w);
			addEdge(u,v,w);
			G[u][v]=G[v][u]=min(G[u][v],w);
		}
		Prim();
		int num,c;
		while(k--){
			scanf("%d%d",&num,&c);
			if(mx[edge[num].u][edge[num].v]<c) printf("No\n");
			else printf("Yes\n");
		}
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值