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为 ...
随机推荐
- 【NodeJs】Ctrl+C在Linux平台和Windows平台下的TCP连接中的不同表现
Linux平台:CentOS release 6.5 (Final) Windows平台:Windows 7 旗舰版 服务器端代码如下: var net = require('net'); var s ...
- Android - Binder驱动
以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删): http://blog.csdn.net/luosh ...
- Mysql中int(1)的误解及说明
在mysql中使用int相关的数据类型时, 如果不太了解其存储方式, 会产生一些误用的情况. 如: 只保存0-9之间的数字, 可能会直接用int(1). 习惯性的以为int(1)就相当于varchar ...
- apache源码编译安装详解
查看是否安装 rpm -qa httpd 如果已安装,则卸载:rpm -e 卸载 --nodeps 不考虑意外 下载 wget http://mirrors.sohu.c ...
- UESTCOJ-BiliBili, ACFun… And More!(水题)
BiliBili, ACFun… And More! Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Ja ...
- chrome跨域配置
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --use ...
- mvc 用户控件 ascx 获取 View 页面的值
<%Html.RenderAction("AscxSideNav", "UI", new {itemName=ViewData["ItemNam ...
- 一行代码实现headView弹簧拉伸效果
前言 很多app的个人中心上部的headView都实现了弹簧拉伸的效果,即tableView的top并不随着下拉而滑动,而是紧紧的停在屏幕的最上方. 我们今天就分析一下这个效果的实现方式. 分析 关键 ...
- Linq XML
写得比较啰嗦,自己记载备用 1 public class XmlFunction 2 { 3 private static XDocument _doc = new ...
- linear model for classification
不同error function比较