DTOJ #5089 沙漠点列

题面

我们称一张无向图是仙人掌,当且仅当这张无向图连通且每条边最多属于一个简单环。我们称一张无向图是沙漠,当且仅当这张无向图中所有连通子图都是仙人掌。

给出一个 n个点,m 条边的沙漠,你可以删去其中的 k 条边。求能分成的连通块数量最大值。

数据范围

3 ≤ n ≤ 1 0 6 , 0 ≤ k ≤ m ≤ 2 × 1 0 6 , 1 ≤ u , v ≤ n 3 \leq n \leq 10^6,0 \leq k \leq m \leq 2 \times10^6,1 \leq u,v \leq n 3n106,0km2×106,1u,vn

题解

显然,由于沙漠的性质,一条边最多属于一条环。
整个图上的边就分为了两种:
1. 1. 1.环上的边
2. 2. 2.非环上的边
接着我们考虑一下断边的情况:
对于环上的边,如果把它断开,当前这块连通块并不能分为2个联通块,因为环断开就变成链了,它还是联通的。得接着断才能把它断成不连通。
对于非环上的边,如果把它断开,当前这块连通块就变成2个连通块了。

于是,基于贪心的思想,我们优先选择断非环边(因为只要断i次就能多i个连通块)断完之后,若k仍有剩余,此时的图一定是若干个环。

思考一下:当我们如果把一个长度为 n n n的环断开了,它就会变成长度为 n n n的链,即有 n n n条非环边。然后就又回到第一种情况。

所以,对于有若干个长度不同的环,我们想要尽可能的通过断开一个环,使得它出现的非环边最大。(断开一个环的代价都是1),这样我们k的消耗就能尽可能的小。

注意事项

判断非环边和环边用dfs即可,记录一下时间戳 d e p i dep_i depi(即dfs序),然后判断对于一个节点 i i i是否有与 j j j相连,并且 0 < d e p j 0 < dep_j 0<depj然后回溯回去即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
inline int read(){
	int k=0,f=1;
	char ch;
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')k=k*10+ch-'0',ch=getchar();
	return k*f;
}
int n,m,k;
int tot_=1,ver[N*4],fst[N],nxt[N*4],v[N];
int huan[N],d[N],tot,ans,ans_1;
inline void add(int x,int y){ver[++tot_]=y;nxt[tot_]=fst[x];fst[x]=tot_;}
void dfs(int x,int fa,int dep){
	v[x]=1;d[x]=dep;
	for(int i=fst[x];i;i=nxt[i]){
		int y=ver[i];
		if(y==fa)continue;
		if(v[y]){
			if(d[y]<d[x]){
			huan[++tot]=d[x]-d[y]+1;
			ans-=huan[tot];
			}
			continue;
		}
		dfs(y,x,dep+1);
	}
}
int main(){
	n=read(),m=read(),k=read();
	for(int i=1;i<=m;++i){
		int x=read(),y=read();
		add(x,y);add(y,x);
	}
	ans=m;
	
	for(int i=1;i<=n;++i)if(!v[i])dfs(i,0,0),ans_1++;
	if(k<=ans){
		printf("%d\n",k+ans_1);
		return 0;
	}
	k-=ans;
	sort(huan+1,huan+tot+1);
	for(int i=tot;i>=1;i--){
		if(k<=huan[i]){
			
			ans+=k-1;
			break;
		}
		ans+=huan[i]-1;
		k-=huan[i];
	}
	printf("%d\n",ans+ans_1);
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值