题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3624

题意:

  给你一个无向图,n个点,m条边。

  有两种边,种类分别用0和1表示。

  让你求一棵生成树,使得这棵树中恰好有k条0种类的边。输出每一条边的两端点和种类。

  若无解,则输出"no solution"。

题解:

  让0和1分别作两种边的边权。

  步骤:

    (1)先找出必须选的0边。(优先选1,最大生成树)

    (2)再将0边个数加至k。

    (3)补上1边。

AC Code:

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <algorithm>
  5. #include <vector>
  6. #define MAX_N 20005
  7.  
  8. using namespace std;
  9.  
  10. struct Edge
  11. {
  12. int sour;
  13. int dest;
  14. int len;
  15. Edge(int _sour,int _dest,int _len)
  16. {
  17. sour=_sour;
  18. dest=_dest;
  19. len=_len;
  20. }
  21. Edge(){}
  22. friend bool operator < (const Edge &a,const Edge &b)
  23. {
  24. return a.len<b.len;
  25. }
  26. };
  27.  
  28. int n,m,k;
  29. int par[MAX_N];
  30. bool failed=false;
  31. vector<Edge> edge;
  32. vector<Edge> est;
  33. vector<Edge> ans;
  34.  
  35. void read()
  36. {
  37. cin>>n>>m>>k;
  38. int a,b,c;
  39. for(int i=;i<m;i++)
  40. {
  41. cin>>a>>b>>c;
  42. edge.push_back(Edge(a,b,c));
  43. }
  44. }
  45.  
  46. void init_union_find()
  47. {
  48. for(int i=;i<=n;i++)
  49. {
  50. par[i]=i;
  51. }
  52. }
  53.  
  54. int find(int x)
  55. {
  56. return par[x]==x?x:par[x]=find(par[x]);
  57. }
  58.  
  59. void unite(int x,int y)
  60. {
  61. int px=find(x);
  62. int py=find(y);
  63. if(px==py) return;
  64. par[px]=py;
  65. }
  66.  
  67. bool same(int x,int y)
  68. {
  69. return find(x)==find(y);
  70. }
  71.  
  72. void max_tree()
  73. {
  74. init_union_find();
  75. sort(edge.begin(),edge.end());
  76. int cnt=;
  77. for(int i=edge.size()-;i>=;i--)
  78. {
  79. Edge temp=edge[i];
  80. if(!same(temp.sour,temp.dest))
  81. {
  82. cnt++;
  83. unite(temp.sour,temp.dest);
  84. if(temp.len==) est.push_back(temp);
  85. }
  86. }
  87. if(cnt!=n- || est.size()>k) failed=true;
  88. }
  89.  
  90. void min_tree()
  91. {
  92. init_union_find();
  93. int cnt=;
  94. int spe=;
  95. for(int i=;i<est.size() && spe<k;i++)
  96. {
  97. Edge temp=est[i];
  98. cnt++;
  99. spe++;
  100. ans.push_back(temp);
  101. unite(temp.sour,temp.dest);
  102. }
  103. for(int i=;i<edge.size();i++)
  104. {
  105. Edge temp=edge[i];
  106. if(!same(temp.sour,temp.dest))
  107. {
  108. if(temp.len==)
  109. {
  110. if(spe<k)
  111. {
  112. cnt++;
  113. spe++;
  114. ans.push_back(temp);
  115. unite(temp.sour,temp.dest);
  116. }
  117. }
  118. else
  119. {
  120. cnt++;
  121. ans.push_back(temp);
  122. unite(temp.sour,temp.dest);
  123. }
  124. }
  125. }
  126. if(cnt!=n- || spe!=k) failed=true;
  127. }
  128.  
  129. void solve()
  130. {
  131. max_tree();
  132. min_tree();
  133. }
  134.  
  135. void print()
  136. {
  137. if(failed)
  138. {
  139. cout<<"no solution"<<endl;
  140. return;
  141. }
  142. for(int i=;i<ans.size();i++)
  143. {
  144. Edge temp=ans[i];
  145. cout<<temp.sour<<" "<<temp.dest<<" "<<temp.len<<endl;
  146. }
  147. }
  148.  
  149. int main()
  150. {
  151. read();
  152. solve();
  153. print();
  154. }

BZOJ 3624 [Apio2008]免费道路:并查集 + 生成树 + 贪心【恰有k条特殊路径】的更多相关文章

  1. bzoj 3624: [Apio2008]免费道路 生成树的构造

    3624: [Apio2008]免费道路 Time Limit: 2 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 111  Solved: 4 ...

  2. BZOJ 3624: [Apio2008]免费道路

    3624: [Apio2008]免费道路 Time Limit: 2 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1201  Solved:  ...

  3. bzoj 3624: [Apio2008]免费道路【生成树+贪心】

    先把水泥路建生成树,然后加鹅卵石路,这里加的鹅卵石路是一定要用的(连接各个联通块),然后初始化并查集,先把必需的鹅卵石路加进去,然后随便加鹅卵石路直到k条,然后加水泥路即可. 注意判断无解 #incl ...

  4. Bzoj 3624: [Apio2008]免费道路 (贪心+生成树)

    Sample Input 5 7 2 1 3 0 4 5 1 3 2 0 5 3 1 4 3 0 1 2 1 4 2 1 Sample Output 3 2 0 4 3 0 5 3 1 1 2 1 这 ...

  5. BZOJ 3624: [Apio2008]免费道路 [生成树 并查集]

    题意: 一张图0,1两种边,构造一个恰有k条0边的生成树 优先选择1边构造生成树,看看0边是否小于k 然后保留这些0边,补齐k条,再加1边一定能构成生成树 类似kruskal的证明 #include ...

  6. BZOJ.3624.[APIO2008]免费道路(Kruskal)

    题目链接 我们发现有些白边是必须加的,有些是多余的. 那么我们先把所有黑边加进去,然后把必须要加的白边找出来. 然后Kruskal,把必须要加的白边先加进去,小于K的话再加能加的白边.然后加黑边. 要 ...

  7. 3624: [Apio2008]免费道路

    Description Input Output Sample Input 5 7 2 1 3 0 4 5 1 3 2 0 5 3 1 4 3 0 1 2 1 4 2 1 Sample Output ...

  8. [Apio2008]免费道路[Kruscal]

    3624: [Apio2008]免费道路 Time Limit: 2 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1292  Solved:  ...

  9. P3623 [APIO2008]免费道路

    3624: [Apio2008]免费道路 Time Limit: 2 Sec Memory Limit: 128 MBSec Special Judge Submit: 2143 Solved: 88 ...

随机推荐

  1. TextView划线 android

    TextView  加下划线 . 中划线 下过如图: // 中划线 textView.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.A ...

  2. vue.js+koa2项目实战(三)登录注册模态框

    登录注册模态框 注: [Vue warn]: Do not use built-in or reserved HTML elements as component id: diaLog 原因:diaL ...

  3. PyInstaller把.py转为.exe

    http://www.pyinstaller.org/ http://blog.csdn.net/hmy1106/article/details/45151409 python pyinstaller ...

  4. Java String 常用函数

    1>获取  1.1:字符串中包含的字符数,也就是字符串的长度.   int length():获取长度  1.2:根据位置获取位置上某个字符.   char charAt(int index) ...

  5. UbuntuServer12.04安装MongoDB,开机自启,服务,权限

    获取最新版本 去http://www.mongodb.org/downloads找最新版的链接 wget http://fastdl.mongodb.org/linux/mongodb-linux-x ...

  6. leetCode 84.Largest Rectangle in Histogram (最大矩形直方图) 解题思路和方法

    Given n non-negative integers representing the histogram's bar height where the width of each bar is ...

  7. mysql 相关博客地址

    MySQL概念学习与逐步上手操作系列(一套完整)   https://www.cnblogs.com/zlslch/category/962962.html

  8. os如何处理键盘的所有按键,显示or不显示,显示是如何显示

    [0]README 0.1) source code and text decription are from orange's implemention of a os , and for comp ...

  9. HttpClient 访问 https 出现peer can't

    package util; import java.security.cert.CertificateException; import javax.net.ssl.SSLContext;import ...

  10. springmvc的过滤器和拦截器

    1 什么是过滤器 过滤器是过滤数据,比如过滤低俗文字,修改字符编码等. 2 什么是拦截器 拦截器中可以用来向ModelAndView中添加通用的数据.这样的好处是对于所有网页的公用部分就不需要在每个c ...