洛谷P2323 [HNOI2006]公路修建问题——题解

题目传送门


思考过程&具体做法:
首先将所有边的价格从小到大排序,然后二分答案,并查集维护是否连通来检验即可。


代码:

#include 
using namespace std;

const int maxn=2e4+1000;
struct stu
{
    int x,y,type,cost,id;
}len[maxn*2],now[maxn],ans1[maxn];
int l,r,ans,n,k,m;
int fa[maxn];

bool cmp(stu t1,stu t2)
{
    return t1.costint find(int x)
{
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}

bool judge(int x)
{
    int cnt=0;
    for(int i=1;i<=x;i++)
    {
        if(len[i].type==1)
        {
            int x=len[i].x,y=len[i].y;
            int p=find(x),q=find(y);
            if(p!=q)
            {
                fa[p]=q;
                cnt++;
                now[cnt].id=len[i].id;
                now[cnt].type=1;
            }
        }
    }
    if(cntreturn 0;
    for(int i=1;i<=x;i++)
    {
        int x=len[i].x,y=len[i].y;
        int p=find(x),q=find(y);
        if(p!=q)
        { 
            fa[p]=q;
            cnt++;
            now[cnt].id=len[i].id;
            now[cnt].type=2;
        }
    }
    if(cnt!=n-1) return 0;
    return 1;
}

bool cmp1(stu t1,stu t2)
{
    return t1.idint main()
{
    scanf("%d%d%d",&n,&k,&m);
    m--;
    for(int i=1;i<=m;i++)
    {
        int x,y,a,b;
        scanf("%d%d%d%d",&x,&y,&a,&b);
        len[i*2-1].x=x;
        len[i*2-1].y=y;
        len[i*2-1].type=1;
        len[i*2-1].cost=a;
        len[i*2-1].id=i;
        len[i*2].x=x;
        len[i*2].y=y;
        len[i*2].type=2;
        len[i*2].cost=b;
        len[i*2].id=i;
    }
    sort(len+1,len+1+2*m,cmp);
    l=1,r=2*m;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        for(int i=1;i<=n;i++) fa[i]=i;
        bool k=judge(mid);
        if(k) 
        { 
            ans=len[mid].cost;
            for(int i=1;i<=n-1;i++) ans1[i]=now[i];
            r=mid-1;
        }
        else l=mid+1;
    }
    sort(ans1+1,ans1+n,cmp1);
    printf("%d\n",ans);
    for(int i=1;i<=n-1;i++) printf("%d %d\n",ans1[i].id,ans1[i].type);
    return 0;
}

你可能感兴趣的:(题解)