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

最小生成树

BZOJ题目传送门
洛谷题目传送门

因为一级公路的花费一定大于二级公路,那么我们当然恰好选 k 条一级公路时是最优的。先以 c 1 为关键字排序选 k 条边,再以 c 2 为关键字排序选 n k 1 条边即可。

代码:

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10005
#define F inline
using namespace std;
struct edge{ int x,y,c1,c2,id,p; }ed[N<<1];
int n,m,k,p,cst,h[N],ans[N],fa[N];
F char readc(){
    static char buf[100000],*l=buf,*r=buf;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    return l==r?EOF:*l++;
}
F int _read(){
    int x=0; char ch=readc();
    while (!isdigit(ch)) ch=readc();
    while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
    return x;
}
F void writec(int x){ if (x>9) writec(x/10); putchar(x%10+48); }
F void _write(int x){ writec(x),puts(""); }
F void write_(int x){ writec(x),putchar(' '); }
F bool cmp1(edge a,edge b){ return a.c1<b.c1; }
F bool cmp2(edge a,edge b){ return a.c2<b.c2; }
F bool cmp3(edge a,edge b){ return a.id<b.id; }
F bool cmp4(int x,int y){ return ed[x].id<ed[y].id; }
int findfa(int x){ return x==fa[x]?x:fa[x]=findfa(fa[x]); }
int main(){
    n=_read(),p=_read(),m=_read()-1;
    for (int i=1,x,y,c1,c2;i<=m;i++){
        x=_read(),y=_read(),c1=_read(),c2=_read();
        ed[++k]=(edge){x,y,c1,c2,i};
    }
    for (int i=1;i<=n;i++) fa[i]=i;
    sort(ed+1,ed+k+1,cmp1);
    for (int i=1,q=0,x,y;q<p;i++)
        if ((x=findfa(ed[i].x))!=(y=findfa(ed[i].y)))
            fa[x]=y,ans[++q]=ed[i].id,cst=max(cst,ed[i].c1),ed[i].p=1;
    sort(ed+1,ed+k+1,cmp2);
    for (int i=1,q=p,x,y,id;q<n-1;i++)
        if (!ed[i].p&&(x=findfa(ed[i].x))!=(y=findfa(ed[i].y)))
            fa[x]=y,ans[++q]=ed[i].id,cst=max(cst,ed[i].c2),ed[i].p=2;
    _write(cst);//sort(ed+1,ed+k+1,cmp3),sort(ans+1,ans+n,cmp4);
//  for (int i=1;i<n;i++)
//      write_(ans[i]),_write(ed[ans[i]].p);
}

猜你喜欢

转载自blog.csdn.net/a1799342217/article/details/80587311
今日推荐