Contest20140709 testA 树型DP
testA
输入文件:
testA.in 输出文件testA.out
时限5000ms
问题描述:
一棵树N个节点,每条边有一个距W,现在定义SUM为所有dist(X,Y)的和1<=X<Y<=N
,
dist(X,Y)表示X到Y在树上的距离。现在给你一个机会把任意一条边删掉,再把这条边连接其他两个节点使得SUM最小。求出SUM的最小值
输入描述:
第一行N。
第二行到第N行每行三个数X,Y,W。表示X到Y有一条长度为W的边。
。
输出描述:
一行一个数表示答案。
数据范围N<=5000 , W<=10^6
样例输入1:
6
1
2 1
2 3 1
3 4 1
4 5 1
5 6 1
样例输出1:
29
样例输入2:
3
1
2 2
1 3 4
样例输出2:
12
就因为这道题卡了我很久啊。总之就是维护一堆乱七八糟的值。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 10000
#define MAXE MAXN*2
#define MAXV MAXN
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
typedef long long qword;
int n,m;
struct edge
{
int x,y;
}el[MAXE];
struct Edge
{
int np,val;
int id;
Edge *next;
}E[MAXE],*V[MAXV];
int root,tope=-;
void addedge(int x,int y,int z,int id)
{
E[++tope].np=y;
E[tope].next=V[x];
E[tope].val=z;
E[tope].id=id;
V[x]=&E[tope];
}
int fa[MAXN];
int dis_fa[MAXN];
int q[MAXN];
int ope=-,clo=;
int dp1[MAXN];//size of subtree
qword dp2[MAXN];//the total distance from each child to the root in subtree
qword dp3[MAXN];//the total distance from each node outside the subtree to root
qword dp4[MAXN];//the total distance of each pair
void bfs(int root)
{
ope=-,clo=;
Edge *ne;
q[]=root;
fa[root]=;
int now;
while (ope<clo)
{
now=q[++ope];
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==fa[now])continue;
fa[ne->np]=now;
dis_fa[ne->np]=ne->val;
q[++clo]=ne->np;
}
}
}
qword work1()
{
int i,j;
Edge *ne;
int now;
for (i=clo;i>=;i--)
{
now=q[i];
dp1[now]=;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==fa[now])continue;
dp1[now]+=dp1[ne->np];
}
}
for (i=clo;i>=;i--)
{
now=q[i];
dp2[now]=;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==fa[now])continue;
dp2[now]+=dp2[ne->np]+dp1[ne->np]*ne->val;
}
}
dp3[q[]]=;
for (i=;i<=clo;i++)
{
now=q[i];
// dp3[now]=dp3[fa[now]]+dp2[fa[now]]-dp2[now]+dis_fa[now]*(-dp1[now]+dp1[fa[now]]-dp1[now]);
dp3[now]=dp3[fa[now]]+dp2[fa[now]]-dp2[now]-dis_fa[now]*dp1[now]+dis_fa[now]*(dp1[root]-dp1[now]);
}
qword ret=;
for (i=;i<=n;i++)
{
ret+=(qword)dis_fa[i]*dp1[i]*(dp1[root]-dp1[i]);
}
return ret;
}
bool edge_st[MAXN];
int color[MAXN];
qword dist[MAXN];
void dfs2(int now,int fat,int col,qword d)
{
color[now]=col;
dist[now]=d;
Edge *ne;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==fat)continue;
dfs2(ne->np,now,col,d+ne->val);
}
}
int main()
{
freopen("testA.in","r",stdin);
//freopen("testA.out","w",stdout);
int i,j,k;
int x,y,z;
scanf("%d",&n);
for (i=;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z,i-);
addedge(y,x,z,i-);
el[i-].x=x;
el[i-].y=y;
}
m=n-;
root=;
bfs(root);
qword sum_old=work1();
//cout<<"SUM_OLD:"<<sum_old<<endl;
qword dis1,dis2;
qword dis_old1,dis_old2;
qword mus1,mus2;
int totm1,totm2;
qword best=;
for (i=;i<m;i++)
{
edge_st[i]=;
if (fa[el[i].x]==el[i].y)swap(el[i].x,el[i].y);
dfs2(el[i].x,el[i].y,,);//1:outside
dfs2(el[i].y,el[i].x,,);//2:inside
dis_old1=dp3[el[i].y]-dis_fa[el[i].y]*(dp1[root]-dp1[el[i].y]);
dis_old2=dp2[el[i].y];
mus1=dp2[el[i].y]+dp1[el[i].y]*dis_fa[el[i].y];
mus2=dp3[el[i].y];
totm1=dp1[el[i].y];
totm2=dp1[root]-dp1[el[i].y];
dis1=dis2=INF;
for (j=;j<=n;j++)
{
if (color[j]==)
{
dis2=min(dis2,dp2[j]+dp3[j]-mus2-totm2*dist[j]);
}else
{
dis1=min(dis1,dp2[j]+dp3[j]-mus1-totm1*dist[j]);
}
}
best=max(best,(dis_old1-dis1)*totm1+(dis_old2-dis2)*totm2);
}
printf(LL "\n",sum_old-best);
return ;
}
Contest20140709 testA 树型DP的更多相关文章
- POJ3659 Cell Phone Network(树上最小支配集:树型DP)
题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. ...
- POJ 3342 - Party at Hali-Bula 树型DP+最优解唯一性判断
好久没写树型dp了...以前都是先找到叶子节点.用队列维护来做的...这次学着vector动态数组+DFS回朔的方法..感觉思路更加的清晰... 关于题目的第一问...能邀请到的最多人数..so ea ...
- 【XSY1905】【XSY2761】新访问计划 二分 树型DP
题目描述 给你一棵树,你要从\(1\)号点出发,经过这棵树的每条边至少一次,最后回到\(1\)号点,经过一条边要花费\(w_i\)的时间. 你还可以乘车,从一个点取另一个点,需要花费\(c\)的时间. ...
- 洛谷P3354 Riv河流 [IOI2005] 树型dp
正解:树型dp 解题报告: 传送门! 简要题意:有棵树,每个节点有个权值w,要求选k个节点,最大化∑dis*w,其中如果某个节点到根的路径上选了别的节点,dis指的是到达那个节点的距离 首先这个一看就 ...
- 【POJ 3140】 Contestants Division(树型dp)
id=3140">[POJ 3140] Contestants Division(树型dp) Time Limit: 2000MS Memory Limit: 65536K Tot ...
- Codeforces 581F Zublicanes and Mumocrates(树型DP)
题目链接 Round 322 Problem F 题意 给定一棵树,保证叶子结点个数为$2$(也就是度数为$1$的结点),现在要把所有的点染色(黑或白) 要求一半叶子结点的颜色为白,一半叶子结点的 ...
- ZOJ 3949 (17th 浙大校赛 B题,树型DP)
题目链接 The 17th Zhejiang University Programming Contest Problem B 题意 给定一棵树,现在要加一条连接$1$(根结点)和$x$的边,求加 ...
- BZOJ 1564 :[NOI2009]二叉查找树(树型DP)
二叉查找树 [题目描述] 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左儿子结点的数据值大,而比它右儿子结点的数据值小. 另一方面,这棵查找树中每个结点都有一个权值,每个结 ...
- Codeforces 149D Coloring Brackets(树型DP)
题目链接 Coloring Brackets 考虑树型DP.(我参考了Q巨的代码还是略不理解……) 首先在序列的最外面加一对括号.预处理出DFS树. 每个点有9中状态.假设0位不涂色,1为涂红色,2为 ...
随机推荐
- OpenStack_Swift源代码分析——创建Ring及加入�设备源代码算法具体分析
1 创建Ring 代码具体分析 在OpenStack_Swift--Ring组织架构中我们具体分析了Ring的具体工作过程,以下就Ring中添加�设备,删除设备,已经又一次平衡的实现过程作具体的介绍. ...
- 保持Service不被Kill掉的方法--双Service守护 && Android实现双进程守护
本文分为两个部分,第一部分为双Service守护,第二部分为双进程守护 第一部分: 一.Service简介:Java.lang.Object ↳Android.content.Context ↳an ...
- NETBSD-DTARCE
http://www.openbsd.org/papers/ https://2015.asiabsdcon.org/timetable.html.en#T3A http://teachbsd.org ...
- RTB日志分析MR程序设计
到新公司三个月了,上个月做的是Beacon项目,详细的设计思想还没有写文档.这两周开始搞Hadoop,开始阅读相关论文.开始编写MR程序.开始写java,大学时用java较多,工作后就一直在用c/c+ ...
- Effective C++ 笔记二 构造/析构/赋值运算
条款05:了解C++默默编写并调用哪些函数 编译器默认声明一个default构造函数.一个copy构造函数.一个copy assignment操作符和一个析构函数.这些函数都是public且inlin ...
- .NET设计模式(7):创建型模式专题总结(Creational Pattern)
):创建型模式专题总结(Creational Pattern) 创建型模式专题总结(Creational Pattern) --.NET设计模式系列之七 Terrylee,2006年1月 转载: ...
- linux导入导出数据库方法 windows导入导出数据库方法
1.使用管理员账号(sys)登录查询字符集信息 第一步:查询LinuxOracle数据库的字符集 select userenv('language') from dual; 查询结果集可能为:AMER ...
- orainstRoot.sh到底执行了哪些操作
1 #!/bin/sh 1 #!/bin/sh 2 AWK=/bin/awk 3 CHMOD=/bin/chmod 4 CHGRP=/bin/chgrp ...
- html-----005
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 一天学完UFLDL
学习UFLDL笔记 第一节 神经网络 神经元长这样 大写W看着有点不习惯.. 激活函数, 就是上面式子中的f. 可以选 sigmoid函数(或者叫 logistic回归,对数几率函数),反正就是这样一 ...