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

V<=50000,E<=100000,所有数据边权为[1,100]中的正整数。

题解

二分+$kruskal$

如果直接$kruskal$求最小生成树,是无法保证白边数量的,那么我们考虑如果改变白边的数量。我们可以把白边全部都加上一个权值,也就是我们二分的值,然后跑最小生成树,同时记录白边数量。当白边数量>=$need$时,$l=mid+1$,否则$r=mid−1$,更新答案就是这棵生成树的权值和减去所有白边的增量。

证明:
我们发现,如果我们给白边增加权值,做最小生成树,由于白边权值增大,导致不容易选白边。记$f(x)$为给白边增加$x$($x$可为负)权值,做最小生成树后,选白边的数量。可以发现,$f(x)$随$x$增大而减小,显然可以二分。
其次,我们发现,由于黑边的权值是不变的,与白边权值不相互影响。同样由于白边之间关系相对不变,必然选出的$need$条白边一定是符合题意的。

 1 #include<map>
 2 #include<ctime>
 3 #include<cmath>
 4 #include<queue>
 5 #include<stack>
 6 #include<cstdio>
 7 #include<string>
 8 #include<vector>
 9 #include<cstring>
10 #include<cstdlib>
11 #include<iostream>
12 #include<algorithm>
13 #define LL long long
14 #define RE register
15 #define IL inline
16 using namespace std;
17 const int V=50000;
18 const int E=100000;
19
20 int mid;
21 int v,e,need,ans,cnt,tmp;
22 struct tt
23 {
24     int u,v,c,col;
25 }edge[E+5];
26
27 IL int Kruskal();
28 bool comp(const tt &a,const tt &b) {return a.c+(a.col^1)*mid<b.c+(b.col^1)*mid;}
29
30 int set[V+5];
31 IL int find(int r) {return set[r]!=-1 ? set[r]=find(set[r]):r;}
32
33 int main()
34 {
35     scanf("%d%d%d",&v,&e,&need);
36     for  (RE int i=1;i<=e;i++) scanf("%d%d%d%d",&edge[i].u,&edge[i].v,&edge[i].c,&edge[i].col);
37     int l=-100,r=100;
38     while (l<=r)
39     {
40         mid=(l+r)>>1;
41         if (Kruskal()>=need) l=mid+1,ans=tmp;
42         else r=mid-1;
43     }
44     printf("%d\n",ans);
45     return 0;
46 }
47
48 IL int Kruskal()
49 {
50     tmp=cnt=0;
51     int k=0;
52     memset(set,-1,sizeof(set));
53     sort(edge+1,edge+1+e,comp);
54     for (RE int i=1;i<=e;i++)
55     {
56         int q=find(edge[i].u);
57         int p=find(edge[i].v);
58         if (p!=q)
59         {
60             k+=edge[i].col^1;
61             set[q]=p;
62             cnt++;
63             tmp+=edge[i].c;
64             if (cnt==v-1) break;
65         }
66     }
67     return k;
68 }

BZOJ能过的解法

感谢Hzoi_Maple!

由于$COGS$数据会有不满足恰好$need$条白边的情况

打个比方有这样的数据:加$0$时大于$need$,加$1$就小于$need$了。

这样应该在跑最小生成树的时候把所有的白边都加上加的那个权值,结果就是最小生成树的权值和减去$need*$加上的权值,多出来的那一部分完全可以当做黑边来看,因为数据是$100000$的,这样就可以了。(来自Hzoi_Maple)

排序的时候,如果边权相同,要把白边放在前面。

要计算当前至多能取多少白边,当然要把白边放前面。由于保证有解,在$cnt>=need$且$cnt$取最小值的方案下,一定能有黑边把多余的白边代替掉。

 1 #include<map>
 2 #include<ctime>
 3 #include<cmath>
 4 #include<queue>
 5 #include<stack>
 6 #include<cstdio>
 7 #include<string>
 8 #include<vector>
 9 #include<cstring>
10 #include<cstdlib>
11 #include<iostream>
12 #include<algorithm>
13 #define LL long long
14 #define RE register
15 #define IL inline
16 using namespace std;
17 const int V=50000;
18 const int E=100000;
19
20 int mid;
21 int v,e,need,ans,cnt,tmp;
22 struct tt
23 {
24     int u,v,c,col,rc;
25 }edge[E+5];
26
27 IL int Kruskal();
28 IL void change();
29 bool comp(const tt &a,const tt &b) {return a.rc==b.rc ? a.col<b.col:a.rc<b.rc;}
30
31 int set[V+5];
32 IL int find(int r) {return set[r]!=-1 ? set[r]=find(set[r]):r;}
33
34 int main()
35 {
36     scanf("%d%d%d",&v,&e,&need);
37     for  (RE int i=1;i<=e;i++) scanf("%d%d%d%d",&edge[i].u,&edge[i].v,&edge[i].c,&edge[i].col);
38     int l=-100,r=100;
39     while (l<=r)
40     {
41         mid=(l+r)>>1;
42         if (Kruskal()>=need) l=mid+1,ans=tmp-need*mid;
43         else r=mid-1;
44     }
45     printf("%d\n",ans);
46     return 0;
47 }
48
49 IL void change()
50 {
51     for (RE int i=1;i<=e;i++) edge[i].rc=edge[i].c+(edge[i].col^1)*mid;
52 }
53 IL int Kruskal()
54 {
55     change();
56     tmp=cnt=0;
57     int k=0;
58     memset(set,-1,sizeof(set));
59     sort(edge+1,edge+1+e,comp);
60     for (RE int i=1;i<=e;i++)
61     {
62         int q=find(edge[i].u);
63         int p=find(edge[i].v);
64         if (p!=q)
65         {
66             k+=edge[i].col^1;
67             set[q]=p;
68             cnt++;
69             tmp+=edge[i].rc;
70             if (cnt==v-1) break;
71         }
72     }
73     return k;
74 }

COGS能过的解法

转载于:https://www.cnblogs.com/NaVi-Awson/p/7252243.html

[BZOJ 2654]tree(陈立杰)相关推荐

  1. BZOJ2654: tree(陈立杰)

    2654: tree(陈立杰) Time Limit: 30 Sec  Memory Limit: 512 MB Submit: 229  Solved: 91 [Submit][Status] De ...

  2. [国家集训队2012]tree(陈立杰)

    1764. [国家集训队2012]tree(陈立杰) ★★★   输入文件: nt2012_tree.in   输出文件: nt2012_tree.out    简单对比 时间限制:3 s   内存限 ...

  3. bzoj 2653: middle(陈立杰)

    首先膜拜clj... 这道题初看没头绪,看了诸多题解后,发现时先二分,在把大于等于它的为1,小于它的为-1,一段区间最大连续和非负就行 然后想了N久都没想通,终于,在昨天在外拜年时想通了,就是以每个数 ...

  4. tree(陈立杰)[国家集训队2012]

    时间限制:3.0s   内存限制:1.0GB [大意] 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. [输入格式] 第一行V,E,ne ...

  5. 最小生成树 tree(陈立杰)

    问题 D: tree 时间限制: 3 Sec 内存限制: 512 MB 提交: 24 解决: 7 [提交][状态][讨论版] 题目描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰 ...

  6. BZOJ2654/COGS1764 [2012国家集训队]tree(陈立杰) [生成树,二分]

    BZOJ传送门,COGS传送门 tree Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V, ...

  7. 姚班学霸陈立杰:16岁保送清华,18岁拿下IOI世界冠军,现摘得FOCS 2019最佳学生论文...

    郭一璞 安妮 发自 凹非寺 量子位 出品  | 公众号 QbitAI 今年的理论计算机顶会FOCS,一位来自浙江湖州的小哥哥一口气中了3篇论文,还拿下了最佳学生论文奖. 而且这不是偶然神迹,类似操作, ...

  8. 陈立杰再获FOCS 2019最佳学生论文奖

    来源:量子星图 本文约700字,建议阅读5分钟. 在计算机科学顶级会议FOCS 2019上,陈立杰"连中三元",共有三篇论文入围,是入围论文最多的研究者之一. 9月7日,第60届I ...

  9. 姚班大神陈立杰最新动向:MIT毕业后将进入诺奖摇篮,成为UC伯克利Miller研究员...

    晓查 发自 凹非寺 量子位 | 公众号 QbitAI 据知情人士透露,陈立杰今从MIT博士毕业后,将加入加州大学伯克利分校,成为该校Miller研究所研究员. 陈立杰是清华大学姚班知名校友,2016年 ...

最新文章

  1. python十进制转八进制_怎样用python进行二进制,八进制,十进制转换
  2. 更改eclipse的Package Explorer的字体
  3. python Hbase Thrift pycharm 及引入包
  4. 成幻Online Judge 1.00 Beta 正式发布 2007.6.22
  5. 限制Apache日志access.log、error.log文件大小
  6. 本期最新 9 篇论文,每一篇都想推荐给你 | PaperDaily #14
  7. velocity参数重新赋值_Velocity(5)——#set指令
  8. 7-n!末尾有几个0
  9. PHP memory_get_usage()管理内存
  10. Oracle基本安全之用户、角色和权限操作
  11. 【底层原理】深入理解Cache (上)
  12. 直播教程 || 虚拟直播设备清单分享,建议收藏~
  13. linux 查看硬盘序号,Linux 查看硬盘序列号 命令
  14. matlab解隐式差分格式,【毕业设计(论文)】二维热传导方程有限差分法的MATLAB实现...
  15. JQuery读取txt文件
  16. PC端如何双开/多开微信(实测可用)
  17. WSUS无法发现客户端
  18. Leetcode-机器人大冒险 (python)
  19. Atitit q2016 qb doc list on home ntpc.docx
  20. 感恩陪伴,链接未来 | Conflux杭州应用开发运营中心成立

热门文章

  1. 在Linux下编写C程序,怎么检查程序是否有内存泄漏?
  2. [react-router] React-Router 4怎样在路由变化时重新渲染同一个组件?
  3. [react] 使用高阶组件(HOC)实现一个loading组件
  4. React开发(204):react代码分割之路由懒加载
  5. Taro+react开发(36)每一个节点要一个view包裹
  6. 前端学习(3278):循环 遍历
  7. react学习(5)----通过设置初始值控制页面render渲染
  8. [html] 写一个类似刮刮卡效果的交互,即鼠标划过时显示号码
  9. [css] 颜色hsla的字母分别表示什么?
  10. 工作284:理解绑定逻辑