题意:找到一个图中是否含有奇环和偶环

题解:

1.用了两种发法。一个就是跟bc给的答案一样,先求弱联通分量。再在环中找奇偶环

2.我想到的一个略微省些代码量的方法。边求联通分量,边推断是否含有奇环偶环。奇环一定能推断出来,可是偶环

可能被两个奇数环取代而没有在遍历中发现

3.解决问题用到鸽巢定理。先推断有n个联通分量。假设有m个奇环(m > n)则一定有两个奇环在一个连通分量

中,两个奇环可以变成一个偶环,(有个地方须要注意就是:对于单点。当作是一个奇环处理)。

总结:

1.開始想到的解题方法跟标答一样,认为并非特别难,写代码的时候感觉特别困。迷迷糊糊的写完了就WA了,睡醒

之后,又一次一句一句检查代码,感觉状态不好的时候写的代码简直就是恶心,错误百出,以后状态不好的时候直接休

2.后来想到这个优化的方法,写了也WA,第二天才发现题目读错了。这个图可能不是联通的,第一种方法的错误代码

居然ac了,感觉以后千万不要死扣一个错误,找不到就做会别的事情。再回过头来继续找的时候。也不要局限于一个

小范围。着眼于全局查错!

第一种标答方法:

#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define MAXM 300005
int n,m,_,e,top,cnt,bcc,odd,even,ans1,ans2;
int first[MAXN],dfn[MAXN],stack[MAXN];
int id[MAXN],color[MAXN],vis[MAXN];
struct Edge
{
int next,v;
}edge[MAXM << 1];
void insert(int u,int v)
{
edge[e].v = v;
edge[e].next = first[u];
first[u] = e++;
}
void bipartite(int u,int bcc)
{
for(int i = first[u];i != -1;i = edge[i].next)if(!vis[i] && !vis[i ^ 1])
{
int v = edge[i].v;
if(id[v] != bcc)continue;
vis[i] = vis[i ^ 1] = true;
if(color[v] && color[u] != color[v])even++;
if(color[u] == color[v])odd++;
else if(!color[v])
{
color[v] = 3 - color[u];
bipartite(v,bcc);
}
}
}
void search(int bcc,int u)
{
even = odd = 0;
color[u] = 1;
bipartite(u,bcc);
if(odd > 1)even = true;
ans1 = max(odd,ans1);
ans2 = max(ans2,even);
}
int dfs(int u,int fa)
{
int lowu = dfn[u] = ++cnt;
stack[++top] = u;
for(int i = first[u];i != -1;i = edge[i].next)if((i ^ 1) != fa)
{
int v = edge[i].v;
if(!dfn[v])
{
int lowv = dfs(v,i);
lowu = min(lowu,lowv);
if(dfn[u] < lowv)
{
bcc++;
do
{
id[stack[top--]] = bcc;
}while(stack[top + 1] != v);
}
}
else lowu = min(lowu,dfn[v]);
}
return lowu;
}
void solve()
{
ans1 = ans2 = 0;
memset(dfn,0,sizeof(dfn));
memset(color,0,sizeof(color));
memset(id,0,sizeof(id));
memset(vis,0,sizeof(vis));
bcc = cnt = top = 0;
for(int i = 1;i <= n;i++)if(!dfn[i])dfs(1,-1);
for(int u = 1;u <= n;u++)
if(!color[u])
{
search(id[u],u);
if(ans1 && ans2)return;
}
}
int main()
{
scanf("%d",&_);
while(_--)
{
scanf("%d%d",&n,&m);
memset(first,-1,sizeof(first));
e = 0;
for(int i = 0;i < m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
insert(u,v),insert(v,u);
}
solve();
if(ans1)puts("YES");
else puts("NO");
if(ans2)puts("YES");
else puts("NO");
}
}

优化后的方法:

#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define MAXM 300005
int n,m,_,e,top,cnt,bcc,odd,even,point;
int first[MAXN],dfn[MAXN],stack[MAXN],color[MAXN];
bool vis[MAXM << 1];
struct Edge
{
int next,v;
}edge[MAXM << 1];
void insert(int u,int v)
{
edge[e].v = v;
edge[e].next = first[u];
first[u] = e++;
}
int dfs(int u)
{
int lowu = dfn[u] = ++cnt;
stack[++top] = u;
for(int i = first[u];i != -1;i = edge[i].next)if(!vis[i] && !vis[i ^ 1])
{
int v = edge[i].v;
vis[i] = vis[i ^ 1] = true;
if(color[v] + color[u] == 3)even++;
if(color[u] == color[v])odd++;
if(!dfn[v])
{
color[v] = 3 - color[u];
int lowv = dfs(v);
lowu = min(lowu,lowv);
if(dfn[u] < lowv)
{
bcc++;
int num = 0;
do
{
num++;
}while(stack[top--] != v);
if(num == 1)point++;
}
}
else lowu = min(lowu,dfn[v]);
}
return lowu;
}
void solve()
{
even = odd = point = 0;
memset(dfn,0,sizeof(dfn));
memset(color,0,sizeof(color));
memset(vis,false,sizeof(vis));
bcc = 0;
cnt = top = 0;
for(int i = 1;i <= n;i++)if(!dfn[i])
{
bcc++;
color[i] = 1;
dfs(i);
}
if(top == 1)point++;
if(point + odd > bcc)even++;
}
int main()
{
scanf("%d",&_);
while(_--)
{
scanf("%d%d",&n,&m);
memset(first,-1,sizeof(first));
e = 0;
for(int i = 0;i < m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
insert(u,v),insert(v,u);
}
solve();
if(odd)puts("YES");
else puts("NO");
if(even)puts("YES");
else puts("NO");
}
}

hdu 5215 Cycle的更多相关文章

  1. HDU.5215.Cycle(判环)

    题目链接 \(Description\) 给定\(n\)个点\(m\)条边的无向图,问是否存在一个长度为奇数/偶数的简单环. \(n\leq 10^5,m\leq 3\times 10^5\). \( ...

  2. HDU 5215 Cycle(dfs判环)

    题意 题目链接 \(T\)组数据,给出\(n\)个点\(m\)条边的无向图,问是否存在一个奇环/偶环 Sol 奇环比较好判断吧,直接判是否是二分图就行了.. 偶环看起来很显然就是如果dfs到一个和他颜 ...

  3. HDU 5782 Cycle —— KMP

    题目:Cycle 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5782 题意:给出两个字符串,判断两个字符串的每一个前缀是否循环相等(比如abc 和 ca ...

  4. HDU 5782 Cycle(KMP+Hash)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5782 [题目大意] 给出两个字符串,判断他们每一个前缀是否循环同构,循环同构的意思就是,字符串首位 ...

  5. HDU 5215 BestCoder"杯中国大学生程序设计冠军赛” 边双连通分量取出子图+二分染色判图内奇偶环

    Cycle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Sub ...

  6. HDU 5782 Cycle(KMP+哈希)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=5782 题意:给出两个长度相等的字符串,输出两个字符的每个前缀是否循环相同. 思路: 如果连个串循环相 ...

  7. HDU 6987 - Cycle Binary(找性质+杜教筛)

    题面传送门 首先 mol 一发现场 AC 的 csy 神仙 为什么这题现场这么多人过啊啊啊啊啊啊 继续搬运官方题解( 首先对于题目中的 \(k,P\)​,我们有若存在字符串 \(k,P,P'\)​ 满 ...

  8. 2015 "BestCoder Cup" Champion

    这场比赛我没有参加,不过就算参加了也估计是被完虐.于是看着题解把大部分题目都搞了一遍. T1:Movie(hdu 5214) 题目大意: 给出N个区间,问能否选出3个互不相交的区间. N<=10 ...

  9. 莫比乌斯反演&各种筛法

    不学莫反,不学狄卷,就不能叫学过数论 事实上大概也不是没学过吧,其实上赛季头一个月我就在学这东西,然鹅当时感觉没学透,连杜教筛复杂度都不会证明,所以现在只好重新来学一遍了(/wq 真·实现了水平的负增 ...

随机推荐

  1. Geeks Union-Find Algorithm Union By Rank and Path Compression 图环算法

    相同是查找一个图是否有环的算法,可是这个算法非常牛逼,构造树的时候能够达到O(lgn)时间效率.n代表顶点数 原因是依据须要缩减了树的高度,也叫压缩路径(Path compression),名字非常高 ...

  2. 【TP3.2】跨库操作和跨域操作

    一.跨库操作:(同一服务器,不同的数据库) 假设UserModel对应的数据表在数据库user下面,而InfoModel对应的数据表在数据库info下面,那么我们只需要进行下面的设置即可. class ...

  3. ssh之为什么要放弃ssh?

    本文经转载, 源出处不详.https://www.cnblogs.com/hackxiyu/p/6849085.html 最近听一些朋友说,招聘面试的很多人简历都差不多,大部分人的简历上面都写了熟悉s ...

  4. HDUOJ------敌兵布阵

    敌兵布阵 Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submissi ...

  5. js中的let和var

    在ES6中,应该尽量使用const和let来声明变量,而尽量避免使用var. var的缺点是它的作用域比较混乱,使用let能够保证清晰的作用域. 下面看一个小例子. var x = 3; if(x== ...

  6. Oracle游标解析

    本节对Oracle中的游标进行详细讲解. 本节所举实例来源Oracle中scott用户下的emp表dept表: 一.游标: 1.概念: 游标的本质是一个结果集resultset,主要用来临时存储从数据 ...

  7. 《JAVA与模式》之桥接模式

    桥接模式是一种结构型模式,它主要应对的是:由于实际的需要,某个类具有两个或两个以上的维度变化,如果只是用继承将无法实现这种需要,或者使得设计变得相当臃肿. 桥接模式的做法是把变化部分抽象出来,使变化部 ...

  8. ant批量运行Jmeter脚本遇到 Content is not allowed in prolog.问题及解决方案

    在执行 最后生成报告的 task 时,一直报下面这个错: TransformerException,  Content is not allowed in prolog. 解决方法:需要修改jmete ...

  9. 关闭VS的实时调试器

    今天要安装一个水晶报表.安装过程有几个文件有错误.结果这个vs的实时调试器老是调出来.而且还是5次跳出来等你取消5次之后,才到默认的忽略的界面.你知道有多烦的,还得看这他,点完一次还要等几秒钟.差点崩 ...

  10. mac 安装android sdk

    1.下载sdk http://www.androiddevtools.cn/ 2.解压下载文件到目标文件夹 tar -xzvf android-sdk_r24.4.1-macosx.zip /User ...