每次求出最长链更新答案后要将最长链上的边权改为-1

写的贼长 还可以优化...

 /*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int MAXN = 1e5 + , MAXM = 2e5 + ;
int to[MAXM << ], nxt[MAXM << ], Head[MAXN], ed = ;
int value[MAXM << ];
inline void addedge(int u, int v, int val)
{
to[++ed] = v;
nxt[ed] = Head[u];
value[ed] = val;
Head[u] = ed;
}
int d[MAXN];
void dfs(int x, int pre)
{
for (int v, i = Head[x]; i; i = nxt[i])
{
v = to[i];
if (v == pre)
{
continue;
}
d[v] = d[x] + value[i];
dfs(v, x);
}
}
void change(int x)
{
for (int v, i = Head[x]; i; i = nxt[i])
{
v = to[i];
if (d[v] == d[x] - )
{
value[i] = value[i ^ ] = -;
change(v);
}
}
}
int s, t, dmx = -;
int ans2 = , vis[MAXN], dpd[MAXN];
void dp(int x)
{
vis[x] = ;
for (int v, i = Head[x]; i; i = nxt[i])
{
v = to[i];
if (vis[v])
{
continue;
}
dp(v);
ans2 = max(ans2, dpd[x] + dpd[v] + value[i]);
dpd[x] = max(dpd[x], dpd[v] + value[i]);
}
}
int main()
{
int anser;
int n, k;
int u, v;
scanf("%d %d", &n, &k);
for (int i = ; i < n; i++)
{
scanf("%d %d", &u, &v);
addedge(u, v, ), addedge(v, u, );
}
anser = * (n - );
d[] = ;
dfs(, );
for (int i = ; i <= n; i++)
{
if (d[i] > dmx)
{
dmx = d[i];
s = i;
}
}
d[s] = ;
dfs(s, );
dmx = -;
for (int i = ; i <= n; i++)
{
if (d[i] > dmx)
{
dmx = d[i];
t = i;
}
}
anser -= d[t] - ;
if (k == )
{
printf("%d\n", anser);
return ;
}
change(t);
dp();
anser -= ans2 - ;
printf("%d\n", anser);
return ;
}

//BZOJ1912

求树直径dp

 void dp(int x)
{
vis[x] = ;
for (int v, i = Head[x]; i; i = nxt[i])
{
v = to[i];
if (vis[v])
{
continue;
}
dp(v);
ans2 = max(ans2, dpd[x] + dpd[v] + value[i]);
dpd[x] = max(dpd[x], dpd[v] + value[i]);
}
}

其实这个dp的作用是先把无根树转化为有根树 再求每个点子树中的最长链和次长链(如果有次长链的话)

则树的直径有两种情况

1.是一个节点的最长链

2.是一个节点的次长链+最长链

我们首先记录直径取最长是在哪个节点 然后在每个节点我们都要记录 次长链是那条边拓展出去和最长链是那条边拓展出去

因为一个节点的最长链和次长链必定是一个边加下一个节点的最长链

这样就可以一个dfs搞定

 /*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int MAXN = 1e5 + , MAXM = 1e5 + ;
int to[MAXM << ], nxt[MAXM << ], Head[MAXN], ed = ;
int value[MAXM << ];
inline void addedge(int u, int v, int val)
{
to[++ed] = v;
nxt[ed] = Head[u];
value[ed] = val;
Head[u] = ed;
}
int mxlen[MAXN], mxlen2[MAXN];
int ansdis = ; //直径大小
int s, t;
int dfs(int x, int pre)
{
int mx1 = , mx2 = ; //当前节点的最长链和次长链长度
int now;
for (int v, i = Head[x]; i; i = nxt[i])
{
v = to[i];
if (v == pre)
{
continue;
}
now = dfs(v, x) + value[i];
if (now > mx1)
{
mx2 = mx1;
mxlen2[x] = mxlen[x];
mx1 = now;
mxlen[x] = i; //更新最长链 原最长链变为次长链
}
else if (now > mx2)
{
mx2 = now;
mxlen2[x] = i; //更新次长链
}
}
if (mx1 + mx2 > ansdis)
{
ansdis = mx1 + mx2;
s = x;
}
return mx1;//返回每个节点的最长链大小
}
int main()
{
int anser;
int n, k;
int u, v;
scanf("%d %d", &n, &k);
for (int i = ; i < n; i++)
{
scanf("%d %d", &u, &v);
addedge(u, v, ), addedge(v, u, );
}
anser = * (n - );
dfs(, );
anser -= ansdis - ;
if (k == )
{
printf("%d\n", anser);
return ;
}
ansdis = ;
for (int i = mxlen[s]; i; i = mxlen[to[i]]) //最长链上的边重置为-1
{
value[i] = value[i ^ ] = -;
}
for (int i = mxlen2[s]; i; i = mxlen[to[i]]) //次长链上的边重置为-1
{
value[i] = value[i ^ ] = -;
}
dfs(, );
anser -= ansdis - ;
printf("%d\n", anser);
return ;
}

BZOJ1912 最长链树形DP的更多相关文章

  1. $Loj10155$ 数字转换(求树的最长链) 树形$DP$

    loj Description 如果一个数x的/约数和/y(不包括他本身)比他本身小,那么x可以变成y,y 也可以变成x.限定所有数字变换在不超过n的正整数范围内进行,求不断进行数字变换且不出现重复数 ...

  2. 中南大学oj 1317 Find the max Link 边权可以为负的树上最长路 树形dp 不能两遍dfs

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1317经典问题:树上最长路,边权可以为负值的,树形dp,不能用两边dfs.反例:5 41 2 22 ...

  3. 【CF1009F】 Dominant Indices (长链剖分+DP)

    题目链接 \(O(n^2)\)的\(DP\)很容易想,\(f[u][i]\)表示在\(u\)的子树中距离\(u\)为\(i\)的点的个数,则\(f[u][i]=\sum f[v][i-1]\) 长链剖 ...

  4. hdu 6501 transaction transaction transaction 最长路/树形DP/网络流

    最长路: 设置一个虚拟起点和虚拟终点,每个点与起点间一条负边,值为这个点书的价值的相反数(代表买书花钱),每个点与终点连一条正边,值为这个点的书的价格(代表卖书赚钱). 然后按照图中给的边建无向边,权 ...

  5. 2019.01.08 bzoj4543: [POI2014]Hotel加强版(长链剖分+dp)

    传送门 代码: 长链剖分好题. 题意:给你一棵树,问树上选三个互不相同的节点,使得这个三个点两两之间距离相等的方案数. 思路: 先考虑dpdpdp. fi,jf_{i,j}fi,j​表示iii子树中离 ...

  6. 牛客网 桂林电子科技大学第三届ACM程序设计竞赛 G.路径-带条件的树的直径变形-边权最大,边数偶数的树上的最长路径-树形dp

    链接:https://ac.nowcoder.com/acm/contest/558/G 来源:牛客网 路径 小猫在研究树. 小猫在研究路径. 给定一棵N个点的树,每条边有边权,请你求出最长的一条路径 ...

  7. HihoCoder1050 树中的最长路 树形DP第三题(找不到对象)

    题意:求出的树中距离最远的两个结点之间相隔的距离. 水题一道,以前只会用路的直径来解. 代码如下: #include<cstdio> #include<cstdlib> #in ...

  8. 【BZOJ4543】[POI2014]Hotel加强版 长链剖分+DP

    [BZOJ4543][POI2014]Hotel加强版 Description 同OJ3522数据范围:n<=100000 Sample Input 7 1 2 5 7 2 5 2 3 5 6 ...

  9. P7581-「RdOI R2」路径权值【长链剖分,dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P7581 题目大意 给出\(n\)个点的有边权有根树,\(m\)次询问一个节点\(x\)的所有\(k\)级儿子两两之 ...

随机推荐

  1. Markdown 介绍

    Markdown 是目前互联网上最流行的写作语言,它使用一些简单的符号(* / ` > [] () #)来标记文本格式,其简洁的语法.优美的格式以及强大的软件支持深受广大网友的喜爱.维基百科上对 ...

  2. 人性化的Requests模块(响应与编码、header处理、cookie处理、重定向与历史记录、代理设置)

    Requests库是第三方模块,需要额外进行安装.Requests是一个开源库 pip install requests 去GitHub下载回来,进入解压文件,运行setup.py 比urllib2实 ...

  3. Kubernetes中的PV和PVC

    K8S引入了一组叫作Persistent Volume Claim(PVC)和Persistent Volume(PV)的API对象,大大降低了用户声明和使用持久化Volume的门槛.在Pod的Vol ...

  4. python定位隐藏元素

    定位隐藏要素的原理: 页面主要通过“display:none”来控制元素不可见.所以我们需要通过javaScript修改display的值得值为display="block,来实现元素定位的 ...

  5. KCP - A Fast and Reliable ARQ Protocol

    KCP - A Fast and Reliable ARQ Protocol README in English 简介 KCP是一个快速可靠协议,能以比 TCP浪费10%-20%的带宽的代价,换取平均 ...

  6. 服务器iptables规则记录

    很多时候,我在我自己的VPS上面部署了Cobalt Strike,可是网上很多叼毛就会扫描我们的VPS,然后发现我们的Cobalt Strike,如果你还建有web delivery,还会被人家下载上 ...

  7. webdriervAPI(WebElement接口常用方法)

    from  selenium  import  webdriver driver  =  webdriver.Chorme() driver.get("http://www.baidu.co ...

  8. LINQ查询表达式详解(1)——基本语法、使用扩展方法和Lambda表达式简化LINQ查询

    简介 使用线程的主要原因:应用程序中一些操作需要消耗一定的时间,比如对文件.数据库.网络的访问等等,而我们不希望用户一直等待到操作结束,而是在此同时可以进行一些其他的操作.  这就可以使用线程来实现. ...

  9. VS2017:"64位调试操作花费的时间比预期要长",无法运行调试解决办法

    关于这个问题网上搜了好久,参考http://www.yishimei123.com/network/685.html这篇文章,最后终于解决了,在此表示非常感谢! 我的环境是:win10+VS2017 ...

  10. idea导入eclipse的web项目

    idea导入eclipse的web项目 一.导入自己的web项目      步骤:File->New->Project from Existing Source... 二.选择项目的所在位 ...