题意

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. codefoces 22E 图论

    有些题还得练练模拟的能力呀 这题一言难尽,他给的 图不是半连通子图呀,我崩溃了 要分好组,然后1给2连,2给3连,.....n给1连.. 具体看代码,我写的比较捞了吧.. #include<io ...

  2. spring cloud微服务快速教程之(四)熔断器(Hystrix)及其工具(Dashboard、Turbine)

    0-为什么需要熔断器 在分布式系统中,各个服务相互调用相互依赖,如果某个服务挂了,很可能导致其他调用它的一连串服务也挂掉或者在不断等待中耗尽服务器资源,这种现象称之为雪崩效应: 未来防止系统雪崩,熔断 ...

  3. CentOS7.2 部署Ceph分布式存储

    1.1 环境准备 主机名 IP地址 ceph-admin 192.168.16.220 ceph-node1,ceph-mon 192.168.16.221 ceph-node2,ceph-mon 1 ...

  4. Stripe支付对接

    一.由于文档丢失原因,我就直接上代码了. 这个Stripe支付可以支持多个币种,我下面就采用"HDK"来参照支付先上一个支付效果图  提示:先上代码,在说明博主自己理解的流程. 一 ...

  5. GitHub上的计算机视觉学习资料推荐

    9月份将要读研,导师是做cv的,最近学习时找到了不少的计算机视觉的资料,记录一下,同时也分享给需要的朋友 assmdx/ComputerVisionDoc AceCoooool/interview-c ...

  6. 输入URI,按下回车发生了什么?

    当我们输入URL,按下回车发生了什么? 这个题目很俗套- -但是是面试经常出现的题目了.今天听尼古拉斯•屌•大斌哥介绍关于从URI到浏览器呈现给我们页面发生了什么.感觉收获颇多.索性就翻阅了一些其他资 ...

  7. 删除centos自带的openjdk

    [wj@master hadoop]$ rpm -qa | grep javajava-1.7.0-openjdk-1.7.0.191-2.6.15.5.el7.x86_64python-javapa ...

  8. Sql Server执行一条Update语句很慢,插入数据失败

    今天同事要我修改服务器数据库里面的2条数据,查看服务器上的SQL Server数据库的时候,发现这几天数据没有添加成功,然后发现磁盘很快就满了,执行Update语句时,执行半天都提示还在执行,查询语句 ...

  9. go slice与函数传值的理解

    go语言中所有的传值方式都是传值操作. 今天遇到了以下代码: func main(){ slice := make([],) fmt.Println(slice) change(s) fmt.Prin ...

  10. FileUpload的控件上传excel

    在一个使用FileUpload的控件上传excel,读取excel的数据 因为上传的路径一直被限定在C:\Program\IIS\Express 一直限制这个文件下, 想要解决这个问题. 在谷歌浏览器 ...