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

  1. POJ3659 Cell Phone Network(树上最小支配集:树型DP)

    题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. ...

  2. POJ 3342 - Party at Hali-Bula 树型DP+最优解唯一性判断

    好久没写树型dp了...以前都是先找到叶子节点.用队列维护来做的...这次学着vector动态数组+DFS回朔的方法..感觉思路更加的清晰... 关于题目的第一问...能邀请到的最多人数..so ea ...

  3. 【XSY1905】【XSY2761】新访问计划 二分 树型DP

    题目描述 给你一棵树,你要从\(1\)号点出发,经过这棵树的每条边至少一次,最后回到\(1\)号点,经过一条边要花费\(w_i\)的时间. 你还可以乘车,从一个点取另一个点,需要花费\(c\)的时间. ...

  4. 洛谷P3354 Riv河流 [IOI2005] 树型dp

    正解:树型dp 解题报告: 传送门! 简要题意:有棵树,每个节点有个权值w,要求选k个节点,最大化∑dis*w,其中如果某个节点到根的路径上选了别的节点,dis指的是到达那个节点的距离 首先这个一看就 ...

  5. 【POJ 3140】 Contestants Division(树型dp)

    id=3140">[POJ 3140] Contestants Division(树型dp) Time Limit: 2000MS   Memory Limit: 65536K Tot ...

  6. Codeforces 581F Zublicanes and Mumocrates(树型DP)

    题目链接  Round 322 Problem F 题意  给定一棵树,保证叶子结点个数为$2$(也就是度数为$1$的结点),现在要把所有的点染色(黑或白) 要求一半叶子结点的颜色为白,一半叶子结点的 ...

  7. ZOJ 3949 (17th 浙大校赛 B题,树型DP)

    题目链接  The 17th Zhejiang University Programming Contest Problem B 题意  给定一棵树,现在要加一条连接$1$(根结点)和$x$的边,求加 ...

  8. BZOJ 1564 :[NOI2009]二叉查找树(树型DP)

    二叉查找树 [题目描述] 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左儿子结点的数据值大,而比它右儿子结点的数据值小. 另一方面,这棵查找树中每个结点都有一个权值,每个结 ...

  9. Codeforces 149D Coloring Brackets(树型DP)

    题目链接 Coloring Brackets 考虑树型DP.(我参考了Q巨的代码还是略不理解……) 首先在序列的最外面加一对括号.预处理出DFS树. 每个点有9中状态.假设0位不涂色,1为涂红色,2为 ...

随机推荐

  1. careercup-数组和字符串1.5

    1.5 利用字符重复出现的次数,编写一个方法,实现基本的字符串压缩功能.比如,字符串”aabcccccaaa“会变成”a2b1c5a3“.若”压缩“后的字符串没有变短,则返回原先的字符串. 类似 le ...

  2. python学习笔记--Django入门二 Django 的模板系统

    为了使网站更干净简洁更容易维护,页面的设计和Python的代码必须分离开.我们可以使用Django的 模板系统 (Template System)来实现这种模式. 几个简单的模板标签(tag):   ...

  3. eclipse同时开两个tomcat

    首先设置环境变量: 接着修改其中一个tomcat下bin文件夹的startup.bat和catalina.bat 将里面所有CATALINA_HOME都修改为CATALINA_HOME2 然后 修改c ...

  4. spring计划任务,springMvc计划任务,Spring@Scheduled,spring定时任务

    spring计划任务,springMvc计划任务,Spring@Scheduled,spring定时任务 >>>>>>>>>>>> ...

  5. 防御SQL注入的方法总结

    这篇文章主要讲解了防御SQL注入的方法,介绍了什么是注入,注入的原因是什么,以及如何防御,需要的朋友可以参考下   SQL 注入是一类危害极大的攻击形式.虽然危害很大,但是防御却远远没有XSS那么困难 ...

  6. <div>相关

    定义 <div>是一个块级元素[会自动换行] 用法 <div>可用于划分独立的一个块状区域,其内部内容显示在<div>的content部分内 结构 [盗用张图] 从 ...

  7. java开发规范总结_代码注释规范

    规范需要平时编码过程中注意,是一个慢慢养成的好习惯 1.基本规则 1.注释应该使代码更加清晰易懂   2.注释要简单明了,只要提供能够明确理解程序所必要的信息就可以了.如果注释太复杂说明程序需要修改调 ...

  8. CSS 链接

    不同的链接可以有不同的样式. 链接样式 链接的样式,可以用任何CSS属性(如颜色,字体,背景等). 特别的链接,可以有不同的样式,这取决于他们是什么状态. 这四个链接状态是: a:link - 正常, ...

  9. 尝试封装自己的js库

    学了js,用过jquery,然后想着让自己在js这一块有更深的提高,就想尝试着封装自己的js库,偶尔就添加自己想到的功能.有参考过其他大牛封装库的方法,不懂的地方也有借鉴过,但代码还是自己想,自己理解 ...

  10. WinForm控件复杂数据绑定常用数据源(对Combobox,DataGridView等控件DataSource赋值的多种方法)

    开始以前,先认识一下WinForm控件数据绑定的两种形式,简单数据绑定和复杂数据绑定. 1) 简单数据绑定 简单的数据绑定是将用户控件的某一个属性绑定至某一个类型实例上的某一属性.采用如下形式进行绑定 ...