[Jzoj] 3845. 简单题

本文探讨了一种特殊的图论问题,即寻找一个给定无向图的美丽生成仙人掌图,其中包含最多数量的边。仙人掌图是一种特殊的无向图,每条边最多属于一个简单环。通过定义美丽生成仙人掌图的特性,文章提出了一种动态规划和贪心策略相结合的方法,以确定最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

dzy 手上有一张n 个点m 条边的联通无向图,仙人掌是一张每条边最多在一个简单环内的联通无向图。他想求这个无向图的生成仙人掌中最多有多少条边。
但是dzy 觉得这个问题太简单了,于是他定义了“美丽的生成仙人掌”,即在一个生成仙人掌中如果满足对于任意编号为i,j(i < j) 的两点,存在一条它们之间的简单路径上面有j-i+1 个点,则这个仙人掌是美丽的。
他现在想要知道这张图的美丽的生成仙人掌中最多有多少条边,你能帮帮他吗?

题目解析

研究题目可以发现,美丽的生成仙人掌中 iiii+1i+ 1i+1 中必定有一条边。所以问题变成了:我们在一条链上加上若干条边使得得到的图是仙人掌且边数量最大。

显而易见,每一条非链边对应了链上的一个区间。于是问题就变成了选出最多数量的线段使得其互不相交。

这个可以用 dp 来实现,令 F[i]为右端点最大为 i 的区间的答案。则有:
F[i]=max(F[j]+1(i和j之间存在一条边),F[i−1])F[i] =max(F[j]+ 1(i 和 j 之间存在一条边),F[i-1])F[i]=max(F[j]+1(ij)F[i1])
对于iiijjj之间存在一条边,可以用到贪心,只取距离最近的点连边。

代码

#include<bits/stdc++.h>
#define ll long long
#define N 100005
using namespace std;
ll x,y,t,n,m;
ll g[N],f[N];
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
	  cin>>x>>y;
	  if(x>y) swap(x,y);
	  if(x<y-1&&g[y]<x)
	   g[y]=x;
	}
	for(int i=1;i<=n;i++)
	 if(g[i]>0)
	 {
	   if(f[g[i]]+1>f[i-1]) f[i]=f[g[i]]+1;
	   else f[i]=f[i-1];
 	 }
 	 else f[i]=f[i-1];
 	 cout<<f[n]+n-1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值