【杂题总汇】HDU-5215 Cycle

◆HDU-5215◆ Cycle

国庆节集训的第三天……讲图论,心情愉快……刷了一堆水题,不过也刷了一些有意思的题

+传送门+ HDU


? 题目

给出一个无向图(无自环,无重边),求该无向图中是否存在奇环、偶环。

多组数据,每组数据第一行为n,m表示点和边的数量,接下来m行每行描述一条边。

对于每组数据,输出两行,第一行输出是否存在奇环,第二行输出是否存在偶环。


? 解析

因为是一个简单图,这道题就简单了很多。

(1)判断奇环

有一类图是不包含奇数环的——二分图,反过来也是这样——二分图是不包含奇数环的图,所以不是二分图的图就一定包含奇数图。我们就只需要判断原图是否是二分图即可~ 黑白染色判断二分图就可以了。

(2)判断偶环

重点和难点基本上就在这儿了。

我们知道对于每一个连通块我们可以生成一棵DFS树,树上存在树边和返祖边(对这方面知识不熟的reader们建议先学了DFS树再看)。而一些树边和一条返祖边就会构成一个环——如果一条返祖边的两端点在DFS树上的路径距离为奇数,那么加上返祖边就形成了一个偶环。

当然形成偶环也不止这一个情况——看下面两种:

所以总结一下——另一种情况,存在两组点(a,b)(c,d),a与b、c与d在树上的距离都为偶数(如果为奇数的话加上一条返祖边就可以直接形成偶数环了),且a->b和c->d的路径相交(点相交即可),那么就存在偶环,即路径2+路径3。

如上图所示,两个返祖边的端点之间的树边有交集 路径1 ,所以它们可以形成偶数环。

(3)具体实现

听起来像需要2次DFS,但是其实只需要一次——DFS可以同时实现判断二分图和树边、返祖边。

由于可能存在多个连通块,所以依次枚举起点u,如果u没有访问过,则从u开始遍历连通块,同时将u先染色。

若当前在节点u,则通过邻接表遍历u的儿子v,注意枚举v时要将v到达u的父亲的情况舍去。若发现v没有被遍历过,则将v染色后继续从v点遍历;否则经过了一条返祖边,判断v的颜色:

① col[v] ≠ col[u] : 则u->v的路径为奇数,二分图染色成功,存在偶环;

② col[v] = col[u] : 则u->v的理解为偶数,存在奇环;遍历u->v的路径,如果路径上有点已经被打上标记,则说明有另外一条返祖边的两端点之间的路径与当前u->v的路径相交,存在偶环,否则将 u->v 的路径上的点全部打上标记;

输出即可。


? 源代码

/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=int(1e5);
int n,m;
vector<int> lnk[N+5];
int col[N+5],fa[N+5];
bool cov[N+5];
bool odd,eve;
void DFS(int u,int pre){
	for(int i=0;i<lnk[u].size();i++){
		int v=lnk[u][i];
		if(v==pre) continue;
		if(col[v]==-1){
			col[v]=!col[u];
			fa[v]=u;
			DFS(v,u);
		}
		else{
			if(col[v]==col[u]){
				odd=true;
				int pnt=u;
				while(!eve){
					if(cov[pnt]) eve=true;
					cov[pnt]=true;
					pnt=fa[pnt];
					if(pnt==v || pnt==-1) break;
				}
			}
			else eve=true;
		}
	}
}
void Clear(){
	memset(cov,false,sizeof cov);
	memset(fa,-1,sizeof fa);
	memset(lnk,0,sizeof lnk);
	memset(col,-1,sizeof col);
	odd=eve=false;
}
int main(){
	int T;scanf("%d",&T);
	while(T--){
		Clear();
		scanf("%d%d",&n,&m);
		for(int i=0;i<m;i++){
			int u,v;
			scanf("%d%d",&u,&v);
			lnk[u].push_back(v);
			lnk[v].push_back(u);
		}
		for(int i=1;i<=n;i++)
			if(col[i]==-1){
				col[i]=1;
				DFS(i,-1);
			}
		printf("%s\n%s\n",odd?"YES":"NO",eve?"YES":"NO");
	}
	return 0;
}

  


The End

Thanks for reading!

- Lucky_Glass

(Tab:如果我有没讲清楚的地方可以直接在邮箱[email protected] email我,在周末我会尽量解答并完善博客~??)

原文地址:https://www.cnblogs.com/LuckyGlass-blog/p/9740772.html

时间: 2024-11-04 03:51:21

【杂题总汇】HDU-5215 Cycle的相关文章

【杂题总汇】HDU多校赛第十场 Videos

[HDU2018多校赛第十场]Videos 最后一场比赛也结束了-- +HDU传送门+ ◇ 题目 <简要翻译> 有n个人以及m部电影,每个人都有一个快乐值.每场电影都有它的开始.结束时间和看了这部电影会得到的快乐值.电影分成两种类型,若同一个人连续(不是时间连续,是顺序连续)看了两部相同类型的电影,他的快乐值会扣除W,数据保证扣除的值不超过电影增加的快乐值. 特别的,一个人换电影不花费时间,即若第一部电影的结束时间等于下一部电影的开始时间,是可以两场都看的:看电影必须看完:一部电影只能一个人看

【杂题总汇】Codeforces-67A Partial Teacher

[Codeforces-67A]Partial Teacher 上周刷了一大堆小紫薯的动态规划的题??--老师给我们布置了一场测试,感觉还好吧--虽然我并不是这么擅长动态规划?? +Codeforces 传送门+ ◇ 题目 <手写翻译> 老师要给n个学生发糖,n个学生排成一队.由于老师有偏见??,对于一对相邻的学生,他会给成绩好的学生多一些糖(严格大于),而成绩好的学生少一些糖(严格小于),若相邻学生成绩相等,那么他们得到的糖的数量也是一样的.每个学生都至少得到一颗糖.求老师最少总共要给学生多

hdu 3641 数论 二分求符合条件的最小值数学杂题

http://acm.hdu.edu.cn/showproblem.php?pid=3641 学到: 1.二分求符合条件的最小值 /*==================================================== 二分查找符合条件的最小值 ======================================================*/ ll solve() { __int64 low = 0, high = INF, mid ; while(low <=

hdu 4961 数学杂题

http://acm.hdu.edu.cn/showproblem.php?pid=4961 先贴个O(nsqrtn)求1-n所有数的所有约数的代码: vector<int>divs[MAXN]; void caldivs() { for(int i=1;i<MAXN;i++) for(int j=i;j<MAXN;j+=i) divs[j].push_back(i); } 有了这个当时理下思路就可写了,但是重复数处理注意: 1.用一个数组vis[]  vis[i]=1表示i存在

【最小生成树杂题】

这里谈一下最小生成树 生成树的概念:连通图G的一个子图如果是一棵包含G的所有顶点的树,则该子图称为G的生成树.生成树是连通图的极小连通子图.所谓极小是指:若在树中任意增加一条边,则将出现一个回路:若去掉一条边,将会使之变成非连通图. 生成树各边的权值总和称为生成树的权.权最小的生成树称为最小生成树. 最小生成树一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.常用于求最小生成树得算法包括kruskal(克鲁斯卡尔)算法或Prim(

_杂题_

杂题集 是个放题的好地方! **** 5.28 **** - BZOJ [3052] 糖果公园 - 据说是一道区间操作的综合题,但现在貌似蹦了? 现在还是太水,之后再来写吧. *************

[杂题]URAL1822. Hugo II&#39;s War

看懂题意的请直接跳过下一坨! 本人有表达障碍! ========================================== 题意: (题意真的很难很难懂啊!!!  去他娘的**) 有一个王国,王国里有一个国王(编号为1),他有(编号为2~n) n-1个臣子(这些臣子并不全和他有直接关系) 然后呢 国王要去打架,但是只有当他的x%个及以上的直系下属(与他有直接关系的臣子)做好打架的准备了,他才能去打架 他的直系下属也有下属,也要其中x%及以上的下属做好打架准备了,那些直系下属才会开始准备

poj 杂题 - 1959 Darts

这一题放在杂题里,是因为我没有用DP,而是使用的枚举,当然是受到了discuss里面的启发. 因为我们只能有三次机会,每一次只可以是固定的63个数,所以枚举感觉更加直观,但是不知道是不是没有DP快. #include<stdio.h> #include<string.h> int n; int Darts[63]; int main(){ int t,c=1,i,j,k,res; scanf("%d",&t); for(i = 0 ;i<=20;i

【线段树I:母题】hdu 1166 敌兵布阵

[线段树I:母题]hdu 1166 敌兵布阵 题目链接:hdu 1166 敌兵布阵 题目大意 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又開始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况. 因为採取了某种先进的监測手段,所以每一个工兵营地的人数C国都掌握的一清二楚,每一个工兵营地的人数都有可能发生变动.可能添加或降低若干人手,但这些都逃只是C国的监视. 中央情报局要研究敌人到底演习什么战术,所以