LOJ:相框(欧拉回路、分类讨论)

该博客主要探讨了一种图论问题,即如何将图中所有点的度数变为2。首先,通过将度数大于2的节点拆分为2度节点和单点,然后处理单点和2度节点,确保每个连通块只保留一个单点,最后将所有链拼接。代码实现中涉及了DFS遍历和连通块的处理。该问题在图的遍历和转换操作中有实际应用。
摘要由CSDN通过智能技术生成

解析

本题是一道if的板子题

抓住关键:使所有点的度数全变为2
首先对于度数大于2的点,把它分为若干2度点(和可能的一个单点)
现在我们只剩下单点和二度点了

接下来分来讨论一下
若有多个连通块,我们要把它们变成链再拼起来
所以我们要把所有连通块的各自的单点拚到只剩下一个
最后把所有链拼起来

若只有一个连通块,把所有的1度点合并即可

对于0的处理:开一个新点

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+1050;
const double eps=1e-6;
inline ll read(){
  ll x=0,f=1;char c=getchar();
  while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
  while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
  return f*x;
}
int n,m;
struct node{
  int to,nxt;
}p[N*10];
int fi[N],cnt;
inline void addline(int x,int y){
  p[++cnt]={y,fi[x]};fi[x]=cnt;return;
}
int du[N];
int ans,num;
bool vis[N],f;
void dfs(int x){
  if(vis[x]) return;
  vis[x]=1;
  if(du[x]>2) ++ans,f=1;
  num+=(du[x]&1);
  for(int i=fi[x];~i;i=p[i].nxt){
    int to=p[i].to;
    dfs(to);
  }
  return;
}
int sum,flag,flag2;
int main(){
  #ifndef ONLINE_JUDGE
  freopen("a.in","r",stdin);
  freopen("a.out","w",stdout);
  #endif
  memset(fi,-1,sizeof(fi));cnt=-1;
  n=read();m=read();
  for(int i=1;i<=m;i++){
    int x=read(),y=read();
    if(!x) x=++n;
    if(!y) y=++n;
    du[x]++;du[y]++;
    addline(x,y);addline(y,x);
  }
  for(int i=1;i<=n;i++){
    if(!vis[i]&&du[i]){
      num=0;f=0;
      flag++;
      dfs(i);
      if(num>0)ans+=(num)/2-1;
      else ans+=f?0:1;
    }
  }
  if(flag==1){
    if(num>0)ans-=(num)/2-1;
    else ans-=f?0:1;
    ans=ans+num/2;
  }
  if(flag>1) ans+=flag;
  printf("%d\n",ans);
  return 0;
}
/*
4a
1 2
2 3
1 3
3 4
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值