【分块答案】【最小生成树】【kruscal】bzoj1196 [HNOI2006]公路修建问题

二分(分块)枚举 边权上限。用kruscal判可行性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int u[20001],v[20001],w1[20001],w2[20001],n,m,K,Limit;
int fa[10001],rank[10002];
void init()
{
    for(int i=1;i<=n;i++) fa[i]=i;
    memset(rank,0,(n+1)*sizeof(int));
}
int findroot(int x)
{
    if(x==fa[x]) return x;
    int rt=findroot(fa[x]);
    fa[x]=rt;
    return rt;
}
void Union(const int &U,const int &V)
{
    if(rank[U]<rank[V]) fa[U]=V;
    else
      {
        fa[V]=U;
        if(rank[U]==rank[V]) ++rank[U];
      }
}
bool Kruscal(int x)//仅仅需要接通即可。
{
    init(); int cnt=0;
    for(int i=1;i<=m;++i) if(w1[i]<=x)
      {
        int f1=findroot(u[i]),f2=findroot(v[i]);
        if(f1!=f2)
          {
            Union(f1,f2);
            ++cnt;
            if(cnt==n-1) return 1;
          }
      }
    if(cnt<K) return 0;
    for(int i=1;i<=m;++i) if(w2[i]<=x)
      {
        int f1=findroot(u[i]),f2=findroot(v[i]);
        if(f1!=f2)
          {
            Union(f1,f2);
            ++cnt;
            if(cnt==n-1) return 1;
          }
      }
    return cnt==n-1?1:0;
}
int main()
{
    scanf("%d%d%d",&n,&K,&m);
    for(int i=1;i<=m;++i)
      {
        scanf("%d%d%d%d",&u[i],&v[i],&w1[i],&w2[i]);
        Limit=max(Limit,w1[i]);
      }
    int sz=sqrt(Limit),last=0;
    for(int i=1;last<=Limit;i+=sz)
      {
        if(Kruscal(i))
          for(int j=last+1;j<=i;++j)
            if(Kruscal(j))
              {
                printf("%d\n",j);
                return 0;
              }
        last=i;
      }
}
posted @   AutSky_JadeK  阅读(246)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト
点击右上角即可分享
微信分享提示