题意

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的更多相关文章

随机推荐

  1. Java并发机制的底层实现原理之volatile应用,初学者误看!

    volatile的介绍: Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现 ...

  2. Python10_代码规范和可读性

    养成好的编程习惯和方法对提升代码可读性至关重要. 1.类.模块.包:不要用下划线,命名要简短 2.类:命名最好以大写开头 3.模块.包:用小写单词 4.变量.函数.方法:可以用下划线提高可读性,尽量都 ...

  3. Mac-安装命令一览表

    最近一直在学习Mac,可谓是撞了南墙撞西墙,各种问题需要动手去解决. 今天整理下在笔者Mac下面的各种命令 苹果自带的命令 sudo git ruby node 需要我们安装的命令 brew gem ...

  4. acwing 102 -利用二分枚举区间平均值

    我真的是服了,看了一晚上发现居然,,,,, 上图吧,话说有人评论没... 对于结果来说,不一定要枚举有序数列,感觉这是一种猜结果的方法,只不过特别精确,令人发指 #include<cstdio& ...

  5. java引用类型的浅拷贝与深拷贝理解

    1.浅拷贝 只会复制地址值,也就是同一个对象两个引用,只是复制了一个引用而已. 2.深拷贝 重新在堆里创建一个新对象给新引用,连同地址值也不一样. 首先要知道Object的clone()方法, pub ...

  6. 020 ceph作openstack的后端存储

    一.使用ceph做glance后端 1.1 创建用于存储镜像的池 [root@serverc ~]#  ceph osd pool create images 128 128 pool 'images ...

  7. 【小技巧】只用css实现带小三角的对话框样式

    一个小小的技巧: 如图所示,这种小三角,不用图片,只用css怎么实现呢? 直接上代码吧: <!DOCTYPE html> <html> <head> <tit ...

  8. $HDU$ 4336 $Card\ Collector$ 概率$dp$/$Min-Max$容斥

    正解:期望 解题报告: 传送门! 先放下题意,,,已知有总共有$n$张卡片,每次有$p_i$的概率抽到第$i$张卡,求买所有卡的期望次数 $umm$看到期望自然而然想$dp$? 再一看,哇,$n\le ...

  9. 利用log4net创建日志文件时过滤日志,这是坑还是?

    前言 网上貌似没有太多关于log4net过滤日志的资料,在研究过程中发现一点小问题,这里做下记录,希望对后续有用到的童鞋起到一丢丢帮助作用. log4net日志过滤 由于是在.NET Core中使用, ...

  10. 10.Python中print函数中中逗号和加号的区别

    先看看print中逗号和加号分别打印出来的效果.. 这里以Python3为例 1 print("hello" + "world") helloworld 1 p ...