BZOJ 1083 繁忙的都市

 拿到这个题第一反应想到了wikioi里的“舒适的路线”,便想到了最最暴力的解法:枚举每个点,从此点开始每次都做一遍最小生成树,然后按以下程序判断

    (1)是否连通 (2)边数是否小于当前记录的最小边数 (3)最大价值是否最小

于是便得到了下面的代码:

#include
#include
#include
#include
#define INF (1<<30)
#define MAXN 310
#define MAXM 100000
using namespace std;
int f[MAXN];
int x[MAXM],y[MAXM],r[MAXM],w[MAXM];
int mem[MAXM];
int cmp(const int a,const int b){
    return w[a]

时间是费得长了点,幸而过了。

然后在网上搜题解,看到了“二分”这个神方法。基本思想是枚举答案,看在此答案下是否符合题意,就得到了如下代码:

#include
#include
#include
#include
#define INF (1<<30)
#define MAXN 1010
#define MAXM 100000
using namespace std;
int f[MAXN];
int n,m;
struct node{
	int a,b,c;
}e[MAXM];
bool cmp(const node &h,const node &k){
	return h.c=e[i].c){
			int p=getf(e[i].a),q=getf(e[i].b);
			if(p!=q) f[p]=q;
		}
	for(int i=2;i<=n;i++) if(getf(1)!=getf(i)) return false;
	return true;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
	}
	sort(e+1,e+m+1,cmp);
	int left=1;
	int right=m;
	int ans;
	while(left<=right){
		int mid=(left+right) >> 1;
		if(getans(e[mid].c)){
			 right=mid-1;
			 ans=e[mid].c;
		}
		else left=mid+1;
	} 
	printf("%d %d\n",n-1,ans);
    return 0;
}




你可能感兴趣的:(BZOJ 1083 繁忙的都市)