1. 程式人生 > >BZOJ_1196_[HNOI2006]公路修建問題_kruskal+二分答案

BZOJ_1196_[HNOI2006]公路修建問題_kruskal+二分答案

check find for i++ () algorithm 二分答案 include 不能

BZOJ_1196_[HNOI2006]公路修建問題_kruskal+二分答案

題意:http://www.lydsy.com/JudgeOnline/problem.php?id=1196

分析:

先把所有路都拆成兩條。

二分答案mid,把大於mid的邊除去,優先加一級公路,判斷能不能加進去k條。

代碼:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 using namespace std;
 5 #define N 10050
 6 struct A{
 7     int
a,b,v; 8 }e[N<<2]; 9 int n,m,k,fa[N],usex[N<<1],usey[N<<1]; 10 int find(int x){ 11 return fa[x]^x?fa[x]=find(fa[x]):x; 12 } 13 bool check(int x){ 14 for(int i=1;i<=n;i++)fa[i]=i; 15 int ne=0; 16 for(int i=1;i<=m;i++){ 17 if(e[i].v>x)continue; 18
int dx=find(e[i].a),dy=find(e[i].b); 19 if(dx!=dy){ 20 fa[dx]=dy; 21 ne++;if(ne==n-1)return 1; 22 } 23 }if(ne<k)return 0; 24 for(int i=m+1;i<=2*m;i++){ 25 if(e[i].v>x)continue; 26 int dx=find(e[i].a),dy=find(e[i].b);
27 if(dx!=dy){ 28 fa[dx]=dy;ne++;if(ne==n-1)return 1; 29 } 30 }return 0; 31 } 32 int main(){ 33 scanf("%d%d%d",&n,&k,&m);m--; 34 int x,y,z,w; 35 for(int i=1;i<=m;i++){ 36 scanf("%d%d%d%d",&x,&y,&z,&w); 37 e[i].a=e[i+m].a=x; 38 e[i].b=e[i+m].b=y; 39 e[i].v=z;e[i+m].v=w; 40 } 41 int l=0,r=1<<30; 42 while(l<r){ 43 int mid=l+r>>1; 44 if(check(mid))r=mid; 45 else l=mid+1; 46 } 47 printf("%d\n",l); 48 for(int i=1;i<=n;i++)fa[i]=i; 49 int ne=0; 50 for(int i=1;i<=m;i++){ 51 if(e[i].v>l)continue; 52 int dx=find(e[i].a),dy=find(e[i].b); 53 if(dx!=dy){ 54 fa[dx]=dy; 55 ne++; 56 usex[i]=1; 57 } 58 } 59 for(int i=m+1;i<=m+m;i++){ 60 if(e[i].v>l)continue; 61 int dx=find(e[i].a),dy=find(e[i].b); 62 if(dx!=dy){ 63 fa[dx]=dy; 64 ne++; 65 usey[i-m]=1; 66 } 67 } 68 for(int i=1;i<=m;i++){ 69 if(usex[i])printf("%d 1\n",i); 70 else if(usey[i])printf("%d 2\n",i); 71 } 72 }

BZOJ_1196_[HNOI2006]公路修建問題_kruskal+二分答案