首页 > 代码库 > [HNOI乱草]

[HNOI乱草]

前言:

poi的想法题刷多了 想刷刷代码题 其他省的可能有点太难了 所以选了一个省开了个刀,嘻嘻`(*∩_∩*)′

 

[HNOI2006]公路修建问题

一开始看错题了草

意思是花费最多的一条公路尽量少,求最大花费的边

语文老师有教过最大的最小 最小的最大 就是二分

二分最多的那一条公路 然后看看第一公路够不够 反正不管总花费 所以全部选第一条 然后再选第二条 然后用并查集看看连不连通就好 sb题

技术分享
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<set>#define Maxn 10010using namespace std;struct node{  int x,y,c;};bool Cmp(const node &x,const node &y){return x.c<y.c;}node S1[Maxn*2],S2[Maxn*2];int N,M,K; int fa[Maxn];inline int find(int x){if(x==fa[x]) return x; else return fa[x]=find(fa[x]);}inline int FindS1(int x){  int L=1,R=M; int ret=-1;  while(L<=R)  {    int mid=(L+R)>>1;    if(S1[mid].c<=x){L=mid+1; ret=mid;}    else R=mid-1;  }  return ret;}inline int FindS2(int x){  int L=1,R=M; int ret=-1;  while(L<=R)  {    int mid=(L+R)>>1;    if(S2[mid].c<=x){L=mid+1; ret=mid;}    else R=mid-1;  }  return ret;}int main(){  //freopen("a.in","r",stdin);  //freopen("a.out","w",stdout);  scanf("%d%d%d",&N,&K,&M);  for(int i=1;i<M;i++)  {    int x,y,c1,c2;    scanf("%d%d%d%d",&x,&y,&c1,&c2);    node x1; x1.x=x; x1.y=y; x1.c=c1;    node x2; x2.x=x; x2.y=y; x2.c=c2;    S1[i]=x1; S2[i]=x2;  }  sort(S1+1,S1+M+1,Cmp);  sort(S2+1,S2+M+1,Cmp);  int L=1; int R=30000; int ret=-1;  while(L<=R)  {    int mid=(L+R)>>1;    int it1=FindS1(mid);    int it2=FindS2(mid); int it;    if(it1<K){L=mid+1; continue;}    else if(it1+it2<N-1){L=mid+1; continue;}    for(int i=1;i<=N;i++) fa[i]=i; int sum=0;    for(it=1;it<=it1;it++)    {      int xx=find(S1[it].x); int yy=find(S1[it].y);      if(xx!=yy){sum++; fa[xx]=yy;}    }    if(sum<K){L=mid+1; continue;}        for(it=1;it<=it2;it++)    {      int xx=find(S2[it].x); int yy=find(S2[it].y);      if(xx!=yy){sum++; fa[xx]=yy;}    }    if(sum==N-1){ret=mid; R=mid-1; continue;}    else {L=mid+1; continue;}  }  printf("%d\n",ret);  return 0;}/*10 4 203 9 6 31 3 4 15 3 10 28 9 8 76 8 8 37 1 3 24 9 9 510 8 9 12 6 9 16 7 9 82 6 2 13 8 9 53 2 9 61 6 10 35 6 3 12 7 6 17 8 6 210 9 2 17 1 10 2*/
View Code

 

[HNOI乱草]