CF572_Div2_D2
题意
http://codeforces.com/contest/1189/problem/D2
思考
显然地,如果出现度数为2且两条出边边权不相同的情况,是无法构造合法方案的。
下面考虑缩边后的树,此时每个非叶子节点的度数一定大于等于3。
枚举每个非叶子节点,将其重新作为树的根,并尝试将它所有的出边都达到要求。我们先找到它代表的所有叶子,分两种情况考虑:
1.一条边以下只有一个叶子。如下图所示,红色的路径代表+w/2,w为该边的边权,蓝色路径代表-w/2,能达到平衡。
2.一条边以下不止一个叶子。如下图所示,我们要求选定边的子树中挑出的两个叶子的lca的深度必须最大,否则无法消除影响。此处可以挑选dfn最大和最小的那两个。
总复杂度O(n^2)。注意特判一条链的情况。
代码
- #include<bits/stdc++.h>
- using namespace std;
- const int maxn=2E3+;
- int n;
- int deg[maxn*],hh[maxn];
- int tot,haha;
- bool dot[maxn];
- vector<int>what[maxn];
- vector<int>wait;
- double w[maxn];
- map<pair<int,int>,bool>vis;
- inline pair<int,int>M(int x,int y)
- {
- if(x>y)
- swap(x,y);
- return make_pair(x,y);
- }
- struct edge
- {
- int to,next;
- double w;
- };
- struct note
- {
- int x,y;
- double d;
- note(int a=,int b=,double c=)
- {
- x=a,y=b,d=c;
- }
- };
- vector<note>ans;
- struct graph
- {
- int head[maxn*],size;
- edge E[maxn*];
- inline void add(int u,int v,double w)
- {
- E[++size].to=v;
- E[size].next=head[u];
- E[size].w=w;
- head[u]=size;
- }
- void get(int u,int F,int num)
- {
- for(int i=head[u];i;i=E[i].next)
- {
- int v=E[i].to;
- if(v==F)
- continue;
- if(u==F)
- {
- w[++num]=E[i].w;
- hh[num]=v;
- get(v,u,num);
- }
- else
- get(v,u,num);
- }
- if(deg[u]==)
- what[num].push_back(u);
- if(u==F)
- for(int i=;i<=num;++i)
- {
- if(vis[M(u,hh[i])])
- continue;
- if(what[i].size()==)
- {
- int u1=what[i][];
- int x=what[i+<=num?i+:i+-num][];
- int y=what[i+<=num?i+:i+-num][];
- double d=w[i]/;
- ans.push_back(note(u1,x,d));
- ans.push_back(note(u1,y,d));
- ans.push_back(note(x,y,-d));
- vis[M(u,hh[i])]=;
- }
- else
- {
- int u1=what[i][],u2=what[i][what[i].size()-];
- int x=what[i+<=num?i+:i+-num][];
- int y=what[i+<=num?i+:i+-num][];
- double d=w[i]/;
- ans.push_back(note(u1,x,d));
- ans.push_back(note(u2,y,d));
- ans.push_back(note(u1,u2,-d));
- ans.push_back(note(x,y,-d));
- vis[M(u,hh[i])]=;
- }
- }
- }
- void find(int u,int F,int last)
- {
- dot[u]=;
- if(deg[u]!=)
- {
- haha=last;
- wait.push_back(u);
- return;
- }
- for(int i=head[u];i;i=E[i].next)
- {
- int v=E[i].to;
- if(v==F)
- continue;
- if(last==)
- {
- find(v,u,E[i].w);
- last=E[i].w;
- }
- else if(last==E[i].w)
- find(v,u,E[i].w);
- else
- {
- cout<<"NO"<<endl;
- exit();
- }
- }
- }
- int sum;
- void getsize(int u,int F)
- {
- ++sum;
- for(int i=head[u];i;i=E[i].next)
- {
- int v=E[i].to;
- if(v==F)
- continue;
- getsize(v,u);
- }
- }
- }source,G;
- int main()
- {
- ios::sync_with_stdio(false);
- cin>>n;
- for(int i=;i<=n;++i)
- {
- int x,y;
- double z;
- cin>>x>>y>>z;
- source.add(x,y,z);
- source.add(y,x,z);
- ++deg[x],++deg[y];
- }
- int P1=,P2=;
- for(int u=;u<=n;++u)
- {
- if(deg[u]==)
- {
- if(!dot[u])
- {
- source.find(u,u,);
- wait.clear();
- G.add(wait[],wait[],haha);
- G.add(wait[],wait[],haha);
- P1=wait[],P2=wait[];
- }
- continue;
- }
- for(int i=source.head[u];i;i=source.E[i].next)
- {
- int v=source.E[i].to;
- haha=source.E[i].w;
- if(deg[v]!=)
- G.add(u,v,source.E[i].w);
- }
- }
- cout<<"YES"<<endl;
- G.getsize(P1,P1);
- if(G.sum==)
- {
- cout<<<<endl;
- cout<<P1<<" "<<P2<<" "<<haha<<endl;
- return ;
- }
- for(int u=;u<=n;++u)
- {
- if(deg[u]==)
- continue;
- for(int i=;i<=n;++i)
- what[i].clear();
- G.get(u,u,);
- }
- int del=;
- for(int i=;i<ans.size();++i)
- if(abs(ans[i].d-)<=0.01)
- ++del;
- cout<<ans.size()-del<<endl;
- for(int i=;i<ans.size();++i)
- if(abs(ans[i].d-)>0.01)
- cout<<ans[i].x<<" "<<ans[i].y<<" "<<ans[i].d<<endl;
- return ;
- }
CF572_Div2_D2的更多相关文章
随机推荐
- Windows 服务安装与卸载 (通过 installutil.exe)
1. 安装 安装 .NET Framework ; 新建文本文件,重命名为 ServiceInstall.bat,将 ServiceInstall.bat 的内容替换为: C:\\Windows\\M ...
- SQL SQL Index SEEK VS Lookup
SEEK - find everything from index Lookup - find key from index, then visit table to find other row d ...
- Qt和c/c++connect函数冲突解决方法
在使用c/c++的connect函数时在前面写::connect()这样就可以解决了
- 利用Feed43为网站自制RSS源
什么是RSS,它可以做什么 快2020年了,RSS日渐式微,我也是去年机缘巧合下才开始使用的,以前只是听说过.RSS,全称Really Simple Syndication,又称简易信息聚合(也叫聚合 ...
- 20191121-10 Scrum立会报告+燃尽图 06
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/10070 一:组名: 组长组 组长:杨天宇 组员:魏新 罗杨美慧 王歆 ...
- ES6异步操作之Promise
一直以来觉得异步操作在我心头像一团迷雾,可是它重要到我们非学不可,那就把它的面纱解开吧. ES6 诞生以前,异步编程的方法,大概有下面四种. 回调函数 事件监听 发布/订阅 Promise 对象 异步 ...
- 「BZOJ1385」「Baltic2000」Division expression 解题报告
Division expression Description 除法表达式有如下的形式: \(X_1/X_2/X_3.../X_k\) 其中Xi是正整数且\(X_i \le 1000000000(1 ...
- 个人博客-vue-blog
http://47.100.126.169/zmengBlog/
- EXE和DLL调用关系,DLL制作,钩子
制作DLL时,在cpp种引入了头文件,但头文件里的全局变量在cpp种却不能用 参考大佬博客https://blog.csdn.net/speargod/article/details/88854344 ...
- 【Javascript函数】节流throttle和间隔控制dbounce
一.throttle 函数节流,指把很小时间内触发的N多事件,节流成1个事件. 我们这里说的throttle就是函数节流的意思.再说的通俗一点就是函数调用的频度控制器,是连续执行时间间隔控制.主要应用 ...