BZOJ 1083 繁忙的都市

来源:互联网 发布:淘宝买隐形眼镜靠谱吗 编辑:程序博客网 时间:2024/04/27 19:06

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

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

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

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#define INF (1<<30)#define MAXN 310#define MAXM 100000using 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]<w[b];}int getf(int x){    return f[x]==x ? x : f[x]=getf(f[x]);}int main(){    int n,m;    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++){        int u,v,c;        scanf("%d%d%d",&u,&v,&c);        x[i]=u;        y[i]=v;        w[i]=c;        r[i]=i;    }    sort(r+1,r+m+1,cmp);    int cntm=INF;    int valm=INF;    for(int j=1;j<m;j++){        int cnt=0;        int val=0;        for(int i=1;i<=n;i++) f[i]=i;        for(int i=1;i<=n;i++) mem[i]=1;        bool flag=false;        for(int i=j;i<=m;i++){            int p=getf(x[r[i]]),q=getf(y[r[i]]);            if(p!=q){                f[p]=q;                cnt++;                val=max(w[r[i]],val);                mem[q]+=mem[p];                if(mem[q]==n){                    flag=true;                    break;                }            }           }        if(flag) {            if(cnt<cntm){                cntm=cnt;                valm=val;            }            if(cnt==cntm)                valm=min(val,valm);        }    }     printf("%d %d",cntm,valm);    return 0;}

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

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

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#define INF (1<<30)#define MAXN 1010#define MAXM 100000using 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<k.c;}int getf(int x){return f[x]==x ? x : f[x]=getf(f[x]);}bool getans(int val){for(int i=1;i<=n;i++) f[i]=i;for(int i=1;i<=m;i++)if(val>=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;}




0 0