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的更多相关文章
随机推荐
- slim的简单使用
1.在命令行进入项目根目录,然后用composer下载slim composer require slim/slim "^3.0" 2.下载slim完成后,在php文件中引入req ...
- Adam Harley的卷积神经网络3D视觉化模型
https://m.huxiu.com/article/138857/1.html 最近 Google Tensorflow 做了一个非常直观的神经网络 playground.不夸张地说,现在每个人都 ...
- LeetCode 1 Two Sum——在数组上遍历出花样
本文始发于个人公众号:TechFlow 今天是周末,和大家一起来看一道算法题.这道题是大名鼎鼎的LeetCode的第一题,也是面试当中非常常见的一道面试题.题目不难,但是对于初学者来说应该还是很有 ...
- Python学习3月8号【python编程 从入门到实践】---》笔记(1)
第十章:处理文件和异常 #学习处理文件,让程序能够快速地分析大量的数据#学习错误处理,避免程序在面对意外情形时崩溃#学习异常,是python创建的特殊对象,用于管理程序运行时出现#学习模块json,它 ...
- 洛谷$P3645\ [APIO2015]$雅加达的摩天楼 最短路
正解:最短路 解题报告: 传送门$QwQ$ 考虑暴力连边,发现最多有$n^2$条边.于是考虑分块 对于长度$p_i$小于等于$\sqrt(n)$的边,建立子图$d=p_i$.说下关于子图$d$的定义? ...
- PHP计算每月几周,每周的开始结束日期
PHP计算每月几周,每周的开始结束日期 因为项目中需要一个每周工作计算的功能,具体日期的算法是,把每月拆分成几个周,最后一个星期这个月份的天数不够就补上下个月的. 列如今天8月27星期一,这个月有31 ...
- Lincode刷题No.8
8.Rotate String lintcode 题解1: class Solution { public: /** * @param str: An array of char * @param o ...
- 计算n的阶乘
题目描述 定义一个函数,传入一个整数n,打印n!的值比如:传入3打印:6 <====1*2*3 输入 整数n 输出 整数n的阶乘 样例输入 Copy 3 样例输出 Copy 6 x=in ...
- String字符串,输入一串字符判断其中数字,字母,其他的字符的个数
public class StringClassTest { public static void main(String[] args) { //遍历字符串 String str = "H ...
- 【GeneXus】在WorkWithPlus中如何定义未被包含的页面属性?
在使用GeneXus开发项目的过程中,有很多用户会使用到WorkWithPlus这个模板.通过WorkWithPlus的编辑器,让页面的调整变得极为简单,尤其是响应式页面.在WorkWithPlus的 ...