[BZOJ2654] tree (kruskal & 二分答案)

Description

  给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
  题目保证有解。 

Input

  第一行V,E,need分别表示点数,边数和需要的白色边数。
  接下来E行
  每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)。 

Output

  一行表示所求生成树的边权和。 

Sample Input

2 2 1
0 1 1 1
0 1 2 0

Sample Output

2

HINT

  数据规模和约定
  0:V<=10
  1,2,3:V<=15
  0,..,19:V<=50000,E<=100000
  所有数据边权为[1,100]中的正整数。

Source

Solution

  如果给所有白色边加上一个权值,所形成的最小生成树的白边数会随该权值的增大而减小,满足单调性,可以二分权值。

  排序有一个技巧:我们每次考虑最多可以使用多少条白边,所以排序时若权值相同,白边排前黑边排后。如果排序不管黑边白边,那么所求的白边数会小于期望的答案,可能会导致WA。

  当然黑边在前白边在后也行,题是死的人是活的。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct edge
 4 {
 5     int u, v, w, col;
 6     bool operator < (const edge &rhs) const
 7     {
 8         return w == rhs.w ? col < rhs.col : w < rhs.w;
 9     }
10 }e[100005];
11 int n, m, fa[50005], ans;
12  
13 int getfa(int x)
14 {
15     return fa[x] = x == fa[x] ? x : getfa(fa[x]);
16 }
17  
18 int Kruskal(int x)
19 {
20     int ecnt = 0, wcnt = 0, u, v;
21     ans = 0;
22     for(int i = 1; i <= n; i++)
23         fa[i] = i;
24     for(int i = 1; i <= m; i++)
25         if(!e[i].col) e[i].w += x;
26     sort(e + 1, e + m + 1);
27     for(int i = 1; i <= m; i++)
28     {
29         u = getfa(e[i].u), v = getfa(e[i].v);
30         if(u != v)
31         {
32             fa[v] = u, ans += e[i].w;
33             if(!e[i].col) wcnt++;
34             if(++ecnt >= n) break;
35         }
36     }
37     for(int i = 1; i <= m; i++)
38         if(!e[i].col) e[i].w -= x;
39     return wcnt;
40 }
41  
42 int main()
43 {
44     int k, l = -105, r = 105, mid;
45     cin >> n >> m >> k;
46     for(int i = 1; i <= m; i++)
47         cin >> e[i].u >> e[i].v >> e[i].w >> e[i].col;
48     for(int i = 1; i <= m; i++)
49         e[i].u++, e[i].v++;
50     while(l < r - 1)
51     {
52         mid = (l + r) / 2;
53         if(Kruskal(mid) < k) r = mid;
54         else l = mid;
55     }
56     Kruskal(l);
57     cout << ans - l * k << endl;
58     return 0;
59 }
View Code

 

posted @ 2016-04-21 15:42  CtrlCV  阅读(208)  评论(0编辑  收藏  举报