标签:
前言:
poi的想法题刷多了 想刷刷代码题 其他省的可能有点太难了 所以选了一个省开了个刀,嘻嘻`(*∩_∩*)′
[HNOI2006]公路修建问题 |
一开始看错题了草
意思是花费最多的一条公路尽量少,求最大花费的边
语文老师有教过最大的最小 最小的最大 就是二分
二分最多的那一条公路 然后看看第一公路够不够 反正不管总花费 所以全部选第一条 然后再选第二条 然后用并查集看看连不连通就好 sb题
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<set> #define Maxn 10010 using 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 20 3 9 6 3 1 3 4 1 5 3 10 2 8 9 8 7 6 8 8 3 7 1 3 2 4 9 9 5 10 8 9 1 2 6 9 1 6 7 9 8 2 6 2 1 3 8 9 5 3 2 9 6 1 6 10 3 5 6 3 1 2 7 6 1 7 8 6 2 10 9 2 1 7 1 10 2 */
标签:
原文地址:http://www.cnblogs.com/wohenshuai/p/5857863.html