#4714. 圈

news/2024/12/22 21:55:58/

题目描述

对一张无重边、无自环的 n n n 个点的无向图,定义圈为可以重复经过同一个点多次、但不能多次经过同一条边的环。例如, 1 → 2 → 1 1\to 2\to 1 121 不是一个合法的圈,而 1 → 2 → 3 → 4 → 5 → 3 → 1 1\to 2\to 3\to 4\to 5\to 3\to 1 1234531 是一个合法的圈。

定义无向图的双圈覆盖为:图的若干个圈,使得图中每条边恰好出现在两个圈中(无论方向)。

一个定理:如果一个图有哈密尔顿回路的话,它就一定有双圈覆盖。

现在给定一张无重边、无自环的 n n n 个点的无向图,保证这个图存在哈密尔顿回路(会给出),且每个点的度数至少为 3 3 3

求它的一个双圈覆盖。

题解

首先考虑如果每个点的度都是3的情况,可以发现只能是偶数个点,并且除去环上的边的话就是两两间有连边

于是我们加上环上一半且相间的边,不难发现这个图是个二分图,所以我们可以每条边都只走一遍就走完这张图,同理另一半也是一样,再加上走一个环,这样每条边就恰好经过了两边

现在考虑如果一个点的度大于3的话,可以考虑拆点,并且和原来编号的上一个拆的点相连接,这样我们就回到了度数都为3的情况了

具体的话可以画个图理解一下
在这里插入图片描述

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int T,n,m,c,hd[N],V[N],W[N],pr[N],in[N],vis[N],nx[N],t=1,is[N],k;
vector<int>g[N],a[N];
void add(int u,int v,int w){nx[++t]=hd[u];V[hd[u]=t]=v;W[t]=w;
}
void ins(int u,int v,int w){add(u,v,w);add(v,u,w);
}
void bj(int u,int w){vis[u]=1;for (int i=hd[u];i;i=nx[i])if (W[i] && !vis[V[i]])is[i]=is[i^1]=w,bj(V[i],w^1);
}
void go(int u,int w){vis[u]=0;a[k].push_back(pr[u]);for (int i=hd[u];i;i=nx[i])if (W[i]==w){if (w && !is[i]) continue;if (!vis[V[i]]) continue;go(V[i],w^1);}
}
void work(){scanf("%d%d",&n,&m);c=n;for (int i=1;i<=n;i++)g[i].clear(),g[i].push_back(i),pr[i]=i,in[i]=0;for (int i=1,u,v;i<=m;i++){scanf("%d%d",&u,&v);if (u>v) swap(u,v);if (v==u+1 || (u==1 && v==n))continue;if (in[u]) g[u].push_back(++c),pr[c]=u,u=c;if (in[v]) g[v].push_back(++c),pr[c]=v,v=c;ins(u,v,0);in[u]=in[v]=1;}for (int i=1,v,z;i<=n;i++){v=i+1;if (v>n) v=1;z=g[i].size();ins(g[i][z-1],v,1);for (int j=0;j<z-1;j++)ins(g[i][j],g[i][j+1],1);}k=1;for (int i=1;i<=n;i++) a[k].push_back(i);bj(1,0);for (int i=1;i<=c;i++)if (vis[i]) k++,go(i,0);bj(1,1);for (int i=1;i<=c;i++)if (vis[i]) k++,go(i,0);printf("%d\n",k);for (int l,z,i=1;i<=k;i++){z=a[i].size();l=0;for (int j=1;j<z;j++)if (a[i][j]!=a[i][j-1])l++,a[i][l]=a[i][j];while(a[i][l]==a[i][0]) l--;printf("%d",l+1);for (int j=0;j<=l;j++)printf(" %d",a[i][j]);puts("");a[i].clear();}for (int i=1;i<=c;i++) hd[i]=0;t=1;
}
int main(){for (scanf("%d",&T);T--;work());return 0;
}

http://www.ppmy.cn/news/124701.html

相关文章

HDU4741

额有必要写写了~ 公式啊。 两条直线&#xff1a; 构造方程&#xff1a; 求出公垂线向量&#xff1a; 记公垂线和l1形成的平面为alpha&#xff0c;下面求它&#xff1a; 令&#xff1a; 联立&#xff1a; 不难得到如下代码&#xff1a; #include <iostream> #include &l…

在 Arch Linux 上使用 Docker 运行 Mac OS - Catalina

背景介绍 MacOS默认不对其他电脑平台发布&#xff0c;在 Apple 目前的战略中不把 os 作为可交易的商品&#xff0c;而是一种卖硬件附送的高价值软件。因此对于非 A 家的设备&#xff0c;想要整个 Mac OS 就需要自己想办法了&#xff0c;黑苹果的驱动问题不太好解决 -.- 个人已…

hdu 4747

这题思路有点纠结啊啊啊啊啊&#xff01;&#xff01;&#xff01; 类似于今年多校的线段数&#xff0c;多校的时候是固定左端点&#xff0c;此处是固定右端点。。。这类题还是要多想想维护啊。。。。 考虑一组数&#xff0c;那么最小的肯定是0,1,2...递增的数&#xff0c;那…

朗润国际期货:茶饮争霸赛,你最爱喝哪个?

茶饮争霸赛&#xff0c;你最爱喝哪个&#xff1f; 蜜雪冰城&#xff1a;全国22503个门店&#xff0c;人均消费8.85元瑞幸咖啡&#xff1a;全国7480个门店&#xff0c;人均消费19.34元西巴克&#xff1a;全国6706个门店&#xff0c;人均消费39.59元古茗&#xff1a;全国6688个门…

HDU 4741

题目 求异面直线的间的最短距离&#xff0c;并且求出最短距离的线段在两直线上的点。比赛时&#xff0c;在网上找了个资料&#xff0c;需要解个二元一次的方程&#xff0c;估计自己写龊了&#xff0c;奇葩数据&#xff0c;总会出现误差。 后来重新找了个&#xff0c;在这 先求…

Hdu 4715

打素数表&#xff0c;分类讨论 给出一个偶数n&#xff0c;有这样两个素数a和b&#xff0c;使得na-b&#xff0c;要求ab最小。分三类&#xff1a;1. n0&#xff1b; 2. n<0&#xff1b; 3. n>0. AC代码&#xff1a; #include <cstdio> #include <cstdlib> #in…

HDU4715

思路&#xff1a; 1.不存在输出FAIL的情况 2.素数打表 实现判断素数 和 查找第i个素数 3.二分查找素数表&#xff0c;从比x大的下一个素数now开始&#xff0c;判断这now-n是否素数 /*Code By Aquariuslt*/ /*HDU 4715 Difference Between Primes*/ #include<iostream>…

14443-4

14443-4 传输协议激活 RATS-Request for answer to select 第3节14443-3中&#xff0c;当PCD发出选择命令之后&#xff0c;卡片返回SAK&#xff0c;指示PICC是否支持14443-4。 如果PICC支持14443-4&#xff0c;并且PCD需要进入14443-4层&#xff0c;进行协议层的数据传输&…