题解 CF51F 【Caterpillar】
根据毛毛虫的定义,我们不难发现在双连通分量中的点我们都需要进行合并操作,所以我们先进行\(tarjan\)缩边双连通分量,使原图变成一棵树,缩点对答案产生的贡献为每个双连通分量的\(size-1\)
然后我们继续考虑树的情况,发现,若要将树变成毛毛虫,最优的操作是保留叶子节点和除去叶子后的直径,于是我们记录叶子节点个数\(le\),除去叶子后的直径长度\(dist\)
但可能不止不止一棵树,缩点后可能为森林,所以最后还需将森林合并,我们再记录树的个数\(num\)
则最终答案为\(ans= \displaystyle\sum_{i=1}^{co\_cnt}(siz[i]-1)+co\_cnt-dist-le+num-1\)
其他实现的细节就看代码吧
\(code:\)
#include<bits/stdc++.h>
#define maxn 20010
#define maxm 200010
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,m,ans,num;
struct Edge
{
int x,y;
}ed[maxm];
struct edge
{
int to,nxt;
}e[maxm];
int head[maxn],edge_cnt=1;
void add(int from,int to)
{
e[++edge_cnt]=(edge){to,head[from]};
head[from]=edge_cnt;
}
int dfn[maxn],low[maxn],dfn_cnt;
bool bri[maxn];
void tarjan(int x,int ed)
{
dfn[x]=low[x]=++dfn_cnt;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(!dfn[y])
{
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(dfn[x]<low[y]) bri[i]=bri[i^1]=true;
}
else if(i!=(ed^1)) low[x]=min(low[x],dfn[y]);
}
}
int co_cnt;
int co[maxn],siz[maxn];
void dfs_co(int x)
{
co[x]=co_cnt;
siz[co_cnt]++;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(co[y]||bri[i]) continue;
dfs_co(y);
}
}
void clear()
{
edge_cnt=1;
memset(head,0,sizeof(head));
}
int le;
bool vis[maxn],leaf[maxn];
void dfs_le(int x)
{
vis[x]=true;
bool son=true;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(vis[y]) continue;
son=false;
dfs_le(y);
}
if(son)
{
leaf[x]=true;
le++;
}
}
int nd,maxd,dist;
int dis[maxn];
void dfs_find(int x,int fa,int de)
{
vis[x]=true;
if(de>=maxd)
{
maxd=de;
nd=x;
}
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to,v=1;
if(y==fa||leaf[y]) continue;
dfs_find(y,x,de+v);
}
}
int main()
{
read(n),read(m);
for(int i=1;i<=m;++i)
{
int a,b;
read(a),read(b);
add(a,b),add(b,a);
ed[i]=(Edge){a,b};
}
for(int i=1;i<=n;++i)
if(!dfn[i])
tarjan(i,0);
for(int i=1;i<=n;++i)
{
if(!co[i])
{
co_cnt++;
dfs_co(i);
}
}
for(int i=1;i<=co_cnt;++i)
ans+=siz[i]-1;
clear();
for(int i=1;i<=m;++i)
{
int x=ed[i].x,y=ed[i].y;
if(co[x]==co[y]) continue;
add(co[x],co[y]),add(co[y],co[x]);
}
for(int i=1;i<=co_cnt;++i)
{
if(!vis[i])
{
dfs_le(i);
num++;
int tot=0;
for(int p=head[i];p;p=e[p].nxt) tot++;
if(tot==1)
{
leaf[i]=true;
le++;
}
}
}
memset(vis,0,sizeof(vis));
for(int i=1;i<=co_cnt;++i)
{
if(!vis[i]&&!leaf[i])
{
nd=maxd=0;
dfs_find(i,0,1);
dfs_find(nd,0,1);
dist+=maxd;
}
}
printf("%d",ans+co_cnt-dist-le+num-1);
return 0;
}
题解 CF51F 【Caterpillar】的更多相关文章
- CF51F Caterpillar (边双+树形DP)
题目传送门 题目大意:给你一张n个点m条边的图.每次操作可以把两个点合并成一个(与之相连的边也都要连到新点上).求把图中每个联通块都变成“毛毛虫”的最小操作次数.“毛毛虫”必须是一棵树(可以存在自环) ...
- Educational Codeforces Round 10 A. Gabriel and Caterpillar 模拟
A. Gabriel and Caterpillar 题目连接: http://www.codeforces.com/contest/652/problem/A Description The 9-t ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
随机推荐
- vwware虚拟机网卡的三种模式
这里在虚拟机中必须要保证右上角的两个勾选上 三种模式:简单一个比如宿主机器直接连接路由器上网,那虚拟机和宿主机器是一定的可以上外网,相当于虚拟机直接连接在路由器上面,虚拟机需要配置可以上外网的IP地址 ...
- java程序员软件测试技巧
测试是开发的一个非常重要的方面,可以在很大程度上决定一个应用程序的命运.良好的测试可以在早期捕获导致应用程序崩溃的问题,但较差的测试往往总是导致故障和停机. 测试是开发的一个非常重要的方面,可以在很大 ...
- PV、UV、VV、IP的区别
PV.UV.VV.IP的区别 PV即Page View,网站浏览量 指页面的浏览次数,用于衡量网站用户访问的网页数量.用户每次打开一个页面便记录1次PV,多次打开同一页面则浏览量累计. 一般来说,PV ...
- Spring系列.SpEL表达式
Spring表达式语言 SpEL语言是一种强大的表达式语言,支持在运行时查询和操作对象.SpEL表达式不一定要创建IOC容器后才能使用.用户完全可以单独调用SpEL的API来独立的使用时SpEL表达式 ...
- Vue数据更新页面没有更新问题总结
Vue数据更新页面没有更新问题总结 1. Vue无法检测实例别创建时不存在于data中的property 原因: 由于Vue会在初始化实例时对property执行getter/setter转化,所以p ...
- 暑假集训Day1 整数划分
题目大意: 如何把一个正整数N(N长度<20)划分为M(M>=1)个部分,使这M个部分的乘积最大.N.M从键盘输入,输出最大值及一种划分方式. 输入格式: 第一行一个正整数T(T<= ...
- sql 更新时 实现 数字字段自加1
第一种:直接使用SQL语句,这种方式可以避免并发操作造成的数据不一致问题UPDATE 表名称 SET 列名称 = 列名称 + 1 WHERE …… 第二种:将上面的语句逻辑封装成一个存储过程,加上事务 ...
- P4817 Fruit Feast G
最开始拿到这道题的时候,题目中其实只规定了两种水果的饱食度,可以理解成价值或是重量,在不超过T的情况求最大值.第一眼看过去感觉就是装箱问题(背包),只不过这道题用的是完全背包,但是考虑到喝水的情况,做 ...
- openstack cinder-backup流程与源码分析
在现在的云计算大数据环境下,备份容灾已经变成了一个炙手可热的话题,今天,和大家一起分享一下openstack是怎么做灾备的. [首先介绍快照] snapshot可以为volume创建快照,快照中保存了 ...
- NOIP 2016 洛谷 P2827 蚯蚓 题解
题目传送门 展开 题目描述 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手 ...