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

题目描述

输入输出格式

输入格式:

 

在实际评测时,将只会有m-1行公路

 

输出格式:

 

 

输入输出样例

输入样例#1:
4 2 5
1 2 6 5
1 3 3 1
2 3 9 4
2 4 6 1
3 4 4 2
输出样例#1:
4
2 1
3 2
5 1
输入样例#2:
4 1 5
1 2 6 5
1 3 3 1
2 3 9 4
2 4 6 1
3 4 4 3
输出样例#2:
3
2 1
4 2
5 2

 思路:最优瓶颈生成树。先跑一遍最下生成树,求出k条1级边,然后对于所有的边排序,求出另外的边。

错因:数组开小了。

80分代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 200000
int n,k,m,tot,fa[MAXN],num,maxn=-1;
struct nond{
    int a,b,c1,c2,id;
}edge[MAXN];
struct none{
    int id;
    int c;
}ans[MAXN];
int cmp(nond x,nond y){
    return x.c1<y.c1;
}
int cmp1(nond x,nond y){
    return x.c2<y.c2;
}
int cmp2(none x,none y){
    return x.id<y.id;
}
int find(int x){
    if(fa[x]==x)    return fa[x];
    else return fa[x]=find(fa[x]);
}
int main(){
    scanf("%d%d%d",&n,&k,&m);
    for(int i=1;i<=m;i++){
        int a,b,c,d;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        edge[++tot].a=a;
        edge[tot].b=b;
        edge[tot].c1=c;
        edge[tot].c2=d;
        edge[tot].id=i;
    }
    sort(edge+1,edge+1+tot,cmp);
    for(int i=1;i<=n;i++)    fa[i]=i;
    for(int i=1;i<=tot;i++){
        int dx=find(edge[i].a);
        int dy=find(edge[i].b);
        if(dx==dy)    continue;
        fa[dx]=dy;
        num++;
        maxn=max(edge[i].c1,maxn);
        ans[num].id=edge[i].id;
        ans[num].c=1;
        if(num==k)    break;
    }
    sort(edge+1,edge+1+tot,cmp1);
    for(int i=1;i<=tot;i++){
        int dx=find(edge[i].a);
        int dy=find(edge[i].b);
        if(dx==dy)    continue;
        fa[dx]=dy;
        num++;
        maxn=max(edge[i].c2,maxn);
        ans[num].id=edge[i].id;
        ans[num].c=2;
        if(num==n-1)    break;
    }
    sort(ans+1,ans+1+num,cmp2);
    cout<<maxn<<endl;
    for(int i=1;i<=num;i++)
        cout<<ans[i].id<<" "<<ans[i].c<<endl;
}

AC代码:

#include<cstdio>

const int MAXN = 10100;
struct Edge{
    int x,y,c1,c2;
    bool p1,p2;
}e[50100];
int fa[MAXN];
int n,m,k,ans;
int find(int x)
{
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
bool work(int x)
{
    int cnt = 0;
    for (int i=1; i<=n; ++i) fa[i] = i;
    for (int i=1; i<=m; ++i)
    {
        e[i].p1 = false ;
        if (e[i].c1>x) continue ;
        int rx = find(e[i].x);
        int ry = find(e[i].y);
        if (rx!=ry)
        {
            cnt++;
            fa[rx] = ry;
            e[i].p1 = true;
        }
    }
    if (cnt<k) return false;
    for (int i=1; i<=m; ++i)
    {
        e[i].p2 = false;
        if (e[i].c2>x) continue ;
        int rx = find(e[i].x);
        int ry = find(e[i].y);
        if (rx!=ry)
        {
            cnt++;
            fa[rx] = ry;
            e[i].p2 = true;
        }
    }
    if (cnt!=n-1) return false ;
    return true;
}
int main()
{
    scanf("%d%d%d",&n,&k,&m);
    for (int i=1; i<=m; ++i)
        scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].c1,&e[i].c2);
    int l = 0, r = 30000;
    while (l<=r)
    {
        int mid = (l+r)>>1;
        if (work(mid))
        {
            r = mid-1;
            ans = mid;
        }
        else l = mid+1;
    }
    work(ans);    //重新计算一遍 
    printf("%d\n",ans);
    for (int i=1; i<=m; ++i)
    {
        if (e[i].p1) printf("%d %d\n",i,1);
        if (e[i].p2) printf("%d %d\n",i,2);
    }
    return 0;
}

 

posted @ 2017-08-23 16:18  一蓑烟雨任生平  阅读(157)  评论(1编辑  收藏  举报