BZOJ1718分离的路径
2024-09-02 09:32:44
边双题。
求的就是最少加几条边可以使一个图变成边双联通图。
首先tarjan求一下边双,缩完点变成一颗树,统计度数为1的点(无根树的叶子),把这个数算出来,设为x,则ans=(x+1)/2。
这个可以怎么理解呢?先分一下类,当x为偶数时,想让叶子节点边双联通就好像接到一条边,使之在一个环上(简单环肯定边双应该没问题吧),那么,我们任选两个叶子,将他们接到lca上就可以了,切路径上任意一条边都可以,自己画图看看吧,证明不好证,显然还是挺显然的,总共x/2。
当x为奇数时,把x-1个节点如上处理,剩下一个,肯定要加一条边把他接上去,总共(x+1)/2。
然后根据向下取整,简写为(x+1)/2。
得出结论,使一棵树变成边双的额外边数为(叶子节点数+1)/2。
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
int read(){
int sum=,f=;char x=getchar();
while(x<''||x>''){
if(x=='-') f=-;
x=getchar();
}while(x>=''&&x<=''){
sum=sum*+x-'';
x=getchar();
}return sum*f;
}
struct EDGE{
int ed,nex;
}edge[],edgec[];int first[],firstc[],numc=,num=;
int n,m;
int dfn[],low[],bl[],du[];
int edcc,ord,ans;
bool bridge[];
void add(int st,int ed){
edge[++num].ed=ed;
edge[num].nex=first[st];
first[st]=num;
}
void addc(int st,int ed){
edgec[++numc].ed=ed;
edgec[numc].nex=firstc[st];
firstc[st]=numc;
}
void tarjan(int x,int in_edge){
dfn[x]=low[x]=++ord;
for(int i=first[x];i;i=edge[i].nex){
int y=edge[i].ed;
if(!dfn[y]){
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>dfn[x])
bridge[i]=bridge[i^]=true;
}else if(i!=(in_edge^))
low[x]=min(low[x],dfn[y]);
}
}
void dfs(int x){
bl[x]=edcc;
for(int i=first[x];i;i=edge[i].nex){
int y=edge[i].ed;
if(bl[y]||bridge[i]) continue;
dfs(y);
}
}
int main(){
//freopen("b.in","r",stdin);
n=read();m=read();
for(int i=,x,y;i<=m;i++){
x=read();y=read();
add(x,y);add(y,x);
}
for(int i=;i<=n;i++)
if(!dfn[i]) tarjan(i,);//求桥
for(int i=;i<=n;i++)
if(!bl[i]){
edcc++;
dfs(i);
}
for(int i=;i<=num;i++){
int x=edge[i].ed,y=edge[i^].ed;
// cout<<"x="<<x<<" y="<<y<<" bl[x]=";
// cout<<bl[x]<<" bl[y]="<<bl[y]<<endl;
if(bl[x]==bl[y]) continue;
addc(bl[x],bl[y]);
du[bl[x]]++;
}
for(int i=;i<=edcc;i++)
if(du[i]==) ans++;
printf("%d",(ans+)/);
return ;
}
最新文章
- ajax向后台传递数组
- eclipse中的 Compiler compliance level含义
- Mockups Mockplus 网页原型设计
- mvc 方法只允许ajax访问
- 缓存插件 Spring支持EHCache缓存
- ubuntu的dns设置
- TortoiseSVN使用详细步骤
- python数据分析师面试题选
- Delphi XE5 android 蓝牙通讯传输
- bzoj3294
- 基于Levenberg-Marquardt训练算法的BP网络Python实现
- MyBatis 的Mapper中有小于号的处理
- hdu4729 树链剖分+二分
- Spring学习笔记2——创建Product对象,并在其中注入一个Category对象
- 【Qt编程】Qt学习笔记<;二>;
- [ 随手记 5 ] C/C++ 继承
- 基于vue的实战步骤
- 程序设计实习MOOC / 程序设计与算法(三)第二周测验
- scp的两种方式
- weblogic更改端口