题意

http://codeforces.com/contest/1189/problem/D2


思考

显然地,如果出现度数为2且两条出边边权不相同的情况,是无法构造合法方案的。

下面考虑缩边后的树,此时每个非叶子节点的度数一定大于等于3。

枚举每个非叶子节点,将其重新作为树的根,并尝试将它所有的出边都达到要求。我们先找到它代表的所有叶子,分两种情况考虑:

1.一条边以下只有一个叶子。如下图所示,红色的路径代表+w/2,w为该边的边权,蓝色路径代表-w/2,能达到平衡。

2.一条边以下不止一个叶子。如下图所示,我们要求选定边的子树中挑出的两个叶子的lca的深度必须最大,否则无法消除影响。此处可以挑选dfn最大和最小的那两个。

总复杂度O(n^2)。注意特判一条链的情况。


代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=2E3+;
  4. int n;
  5. int deg[maxn*],hh[maxn];
  6. int tot,haha;
  7. bool dot[maxn];
  8. vector<int>what[maxn];
  9. vector<int>wait;
  10. double w[maxn];
  11. map<pair<int,int>,bool>vis;
  12. inline pair<int,int>M(int x,int y)
  13. {
  14. if(x>y)
  15. swap(x,y);
  16. return make_pair(x,y);
  17. }
  18. struct edge
  19. {
  20. int to,next;
  21. double w;
  22. };
  23. struct note
  24. {
  25. int x,y;
  26. double d;
  27. note(int a=,int b=,double c=)
  28. {
  29. x=a,y=b,d=c;
  30. }
  31. };
  32. vector<note>ans;
  33. struct graph
  34. {
  35. int head[maxn*],size;
  36. edge E[maxn*];
  37. inline void add(int u,int v,double w)
  38. {
  39. E[++size].to=v;
  40. E[size].next=head[u];
  41. E[size].w=w;
  42. head[u]=size;
  43. }
  44. void get(int u,int F,int num)
  45. {
  46. for(int i=head[u];i;i=E[i].next)
  47. {
  48. int v=E[i].to;
  49. if(v==F)
  50. continue;
  51. if(u==F)
  52. {
  53. w[++num]=E[i].w;
  54. hh[num]=v;
  55. get(v,u,num);
  56. }
  57. else
  58. get(v,u,num);
  59. }
  60. if(deg[u]==)
  61. what[num].push_back(u);
  62. if(u==F)
  63. for(int i=;i<=num;++i)
  64. {
  65. if(vis[M(u,hh[i])])
  66. continue;
  67. if(what[i].size()==)
  68. {
  69. int u1=what[i][];
  70. int x=what[i+<=num?i+:i+-num][];
  71. int y=what[i+<=num?i+:i+-num][];
  72. double d=w[i]/;
  73. ans.push_back(note(u1,x,d));
  74. ans.push_back(note(u1,y,d));
  75. ans.push_back(note(x,y,-d));
  76. vis[M(u,hh[i])]=;
  77. }
  78. else
  79. {
  80. int u1=what[i][],u2=what[i][what[i].size()-];
  81. int x=what[i+<=num?i+:i+-num][];
  82. int y=what[i+<=num?i+:i+-num][];
  83. double d=w[i]/;
  84. ans.push_back(note(u1,x,d));
  85. ans.push_back(note(u2,y,d));
  86. ans.push_back(note(u1,u2,-d));
  87. ans.push_back(note(x,y,-d));
  88. vis[M(u,hh[i])]=;
  89. }
  90. }
  91. }
  92. void find(int u,int F,int last)
  93. {
  94. dot[u]=;
  95. if(deg[u]!=)
  96. {
  97. haha=last;
  98. wait.push_back(u);
  99. return;
  100. }
  101. for(int i=head[u];i;i=E[i].next)
  102. {
  103. int v=E[i].to;
  104. if(v==F)
  105. continue;
  106. if(last==)
  107. {
  108. find(v,u,E[i].w);
  109. last=E[i].w;
  110. }
  111. else if(last==E[i].w)
  112. find(v,u,E[i].w);
  113. else
  114. {
  115. cout<<"NO"<<endl;
  116. exit();
  117. }
  118. }
  119. }
  120. int sum;
  121. void getsize(int u,int F)
  122. {
  123. ++sum;
  124. for(int i=head[u];i;i=E[i].next)
  125. {
  126. int v=E[i].to;
  127. if(v==F)
  128. continue;
  129. getsize(v,u);
  130. }
  131. }
  132. }source,G;
  133. int main()
  134. {
  135. ios::sync_with_stdio(false);
  136. cin>>n;
  137. for(int i=;i<=n;++i)
  138. {
  139. int x,y;
  140. double z;
  141. cin>>x>>y>>z;
  142. source.add(x,y,z);
  143. source.add(y,x,z);
  144. ++deg[x],++deg[y];
  145. }
  146. int P1=,P2=;
  147. for(int u=;u<=n;++u)
  148. {
  149. if(deg[u]==)
  150. {
  151. if(!dot[u])
  152. {
  153. source.find(u,u,);
  154. wait.clear();
  155. G.add(wait[],wait[],haha);
  156. G.add(wait[],wait[],haha);
  157. P1=wait[],P2=wait[];
  158. }
  159. continue;
  160. }
  161. for(int i=source.head[u];i;i=source.E[i].next)
  162. {
  163. int v=source.E[i].to;
  164. haha=source.E[i].w;
  165. if(deg[v]!=)
  166. G.add(u,v,source.E[i].w);
  167. }
  168. }
  169. cout<<"YES"<<endl;
  170. G.getsize(P1,P1);
  171. if(G.sum==)
  172. {
  173. cout<<<<endl;
  174. cout<<P1<<" "<<P2<<" "<<haha<<endl;
  175. return ;
  176. }
  177. for(int u=;u<=n;++u)
  178. {
  179. if(deg[u]==)
  180. continue;
  181. for(int i=;i<=n;++i)
  182. what[i].clear();
  183. G.get(u,u,);
  184. }
  185. int del=;
  186. for(int i=;i<ans.size();++i)
  187. if(abs(ans[i].d-)<=0.01)
  188. ++del;
  189. cout<<ans.size()-del<<endl;
  190. for(int i=;i<ans.size();++i)
  191. if(abs(ans[i].d-)>0.01)
  192. cout<<ans[i].x<<" "<<ans[i].y<<" "<<ans[i].d<<endl;
  193. return ;
  194. }

CF572_Div2_D2的更多相关文章

随机推荐

  1. Windows 服务安装与卸载 (通过 installutil.exe)

    1. 安装 安装 .NET Framework ; 新建文本文件,重命名为 ServiceInstall.bat,将 ServiceInstall.bat 的内容替换为: C:\\Windows\\M ...

  2. SQL SQL Index SEEK VS Lookup

    SEEK - find everything from index Lookup - find key from index, then visit table to find other row d ...

  3. Qt和c/c++connect函数冲突解决方法

    在使用c/c++的connect函数时在前面写::connect()这样就可以解决了

  4. 利用Feed43为网站自制RSS源

    什么是RSS,它可以做什么 快2020年了,RSS日渐式微,我也是去年机缘巧合下才开始使用的,以前只是听说过.RSS,全称Really Simple Syndication,又称简易信息聚合(也叫聚合 ...

  5. 20191121-10 Scrum立会报告+燃尽图 06

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/10070 一:组名: 组长组 组长:杨天宇 组员:魏新  罗杨美慧  王歆 ...

  6. ES6异步操作之Promise

    一直以来觉得异步操作在我心头像一团迷雾,可是它重要到我们非学不可,那就把它的面纱解开吧. ES6 诞生以前,异步编程的方法,大概有下面四种. 回调函数 事件监听 发布/订阅 Promise 对象 异步 ...

  7. 「BZOJ1385」「Baltic2000」Division expression 解题报告

    Division expression Description 除法表达式有如下的形式: \(X_1/X_2/X_3.../X_k\) 其中Xi是正整数且\(X_i \le 1000000000(1 ...

  8. 个人博客-vue-blog

    http://47.100.126.169/zmengBlog/

  9. EXE和DLL调用关系,DLL制作,钩子

    制作DLL时,在cpp种引入了头文件,但头文件里的全局变量在cpp种却不能用 参考大佬博客https://blog.csdn.net/speargod/article/details/88854344 ...

  10. 【Javascript函数】节流throttle和间隔控制dbounce

    一.throttle 函数节流,指把很小时间内触发的N多事件,节流成1个事件. 我们这里说的throttle就是函数节流的意思.再说的通俗一点就是函数调用的频度控制器,是连续执行时间间隔控制.主要应用 ...