Codeforces 19E&BZOJ 4424 Fairy(好题)
日常自闭(菜鸡qaq)。不过开心的是看了题解之后1A了。感觉这道题非常好,必须记录一下,一方面理清下思路,一方面感觉自己还没有完全领会到这道题的精髓先记下来以后回想。
题意:给定 n 个点,m 条边的无向图,可以从图中删除一条边,问删除哪些边可以使图变成一个二分图。
看到二分图,我们肯定会想到奇环。要删除一条边使得剩下的图变成二分图,那么必定剩下的图也不能存在奇环。所以要删除的边都必须经过所有的奇环。这比较好想,但是还有一个难想一点的条件,要删除的边也不能经过任何的偶环,这是因为如果这条边经过了偶环,哪怕删除了这条边剩下的边也会形成新的奇环。为什么呢?画一下图就发现,假定奇环长度为A,偶环长度为B,他们共享的边长度为C,那么他们能形成新的长度为A+B-2*C长度的环,显然这个数是奇数。
综上,能删除的边满足上诉两个条件。我们得到这样一个算法:对所有奇环的边+1,对所有偶环的边-1,最后边值等于奇环个数的就是满足条件的边。 那么我们可以考虑用差分完成这个事情,用d[x]代表dfs树进入x点的边的差分值。染色的过程差分,染完色之后计算便值即可。
当然这道题还没完,以上的过程我们只考虑了dfs树边的情况,但是返祖边(非树边)呢?我们继续思考:经过上面的思考我们还是只考虑奇环上的返祖边,仔细画图观察:在dfs搜索树上,一个奇环返祖边只会属于一个奇环。根据我们上边的结论:边必须要经过所有奇环,可以得到:奇环返祖边能满足条件当且仅当图上只有一个奇环。
接下来还得注意一个小细节:自环。自环我们可以当中奇环,但是这种奇环没有返祖边,所以我们得特殊处理。
呼呼,到这里我们终于能AC了。
细节详见代码以注释:
#pragma comment(linker,"/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+;
int n,m,odd,rec,num,col[N],vis[N],tag[N],dfn[N];
vector<int> ans; int cnt=,head[N],nxt[N<<],to[N<<],id[N<<];
void add_edge(int x,int y,int z) {
nxt[++cnt]=head[x]; to[cnt]=y; id[cnt]=z; head[x]=cnt;
} void dfs1(int x,int t,int in) {
col[x]=t; dfn[x]=++num;
for (int i=head[x];i;i=nxt[i]) {
if (i==(in^)) continue; //这样能处理重边的情况
int y=to[i];
if (!col[y]) dfs1(y,-t,i);
else {
if (dfn[x]<dfn[y]) continue; //这是一个细节,dfn[x]比dfn[y]大的才是返祖边
if (col[x]==col[y]) { //奇环
odd++; rec=i;
tag[x]++; tag[y]--;
} else { //偶环
tag[x]--; tag[y]++;
}
}
}
} void dfs2(int x,int in) {
vis[x]=;
for (int i=head[x];i;i=nxt[i]) {
if (i==(in^)) continue;
int y=to[i];
if (!vis[y]) {
dfs2(y,i);
tag[x]+=tag[y]; //累计子树差分值得到 x入边值
}
}
if (tag[x]==odd) ans.push_back(in); //满足条件的边
} int main()
{
cin>>n>>m;
for (int i=;i<=m;i++) {
int x,y; scanf("%d%d",&x,&y);
if (x==y) { //特别处理自环的情况
odd++; add_edge(,,i); rec=cnt; continue;
}
add_edge(x,y,i); add_edge(y,x,i);
} for (int i=;i<=n;i++)
if (!col[i]) dfs1(i,,); //染色
for (int i=;i<=n;i++)
if (!vis[i]) dfs2(i,); //计算边值 if (odd==) {
cout<<m<<endl;
for (int i=;i<=m;i++) printf("%d ",i);
} else {
if (odd==) ans.push_back(rec); //奇环返祖边
cout<<ans.size()<<endl;
sort(ans.begin(),ans.end());
for (int i=;i<ans.size();i++) printf("%d ",id[ans[i]]);
}
return ;
}
Codeforces 19E&BZOJ 4424 Fairy(好题)的更多相关文章
- Codeforces Round #378 (Div. 2) D题(data structure)解题报告
题目地址 先简单的总结一下这次CF,前两道题非常的水,可是第一题又是因为自己想的不够周到而被Hack了一次(或许也应该感谢这个hack我的人,使我没有最后在赛后测试中WA).做到C题时看到题目情况非常 ...
- Codeforces 828B Black Square(简单题)
Codeforces 828B Black Square(简单题) Description Polycarp has a checkered sheet of paper of size n × m. ...
- HYSBZ(BZOJ) 4300 绝世好题(位运算,递推)
HYSBZ(BZOJ) 4300 绝世好题(位运算,递推) Description 给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<= ...
- BZOJ第一页刷题计划
BZOJ第一页刷题计划 已完成:67 / 90 [BZOJ1000]A+B Problem:A+B: [BZOJ1001][BeiJing2006]狼抓兔子:最小割: [BZOJ1002][FJOI2 ...
- http://codeforces.com/gym/100623/attachments E题
http://codeforces.com/gym/100623/attachments E题第一个优化它虽然是镜像对称,但它毕竟是一一对称的,所以可以匹配串和模式串都从头到尾颠倒一下第二个优化,与次 ...
- http://codeforces.com/gym/100623/attachments H题
http://codeforces.com/gym/100623/attachments H题已经给出来的,包括后来添加的,都累加得到ans,那么从1-ans都是可以凑出来的,如果ans<a[n ...
- Codeforces Round #612 (Div. 2) 前四题题解
这场比赛的出题人挺有意思,全部magic成了青色. 还有题目中的图片特别有趣. 晚上没打,开virtual contest打的,就会前三道,我太菜了. 最后看着题解补了第四道. 比赛传送门 A. An ...
- bzoj 4424: Cf19E Fairy && codeforces 19E. Fairy【树形dp】
参考:https://blog.csdn.net/heheda_is_an_oier/article/details/51131641 这个找奇偶环的dp1真是巧妙,感觉像tarjan一样 首先分情况 ...
- Guard Duty (medium) Codeforces - 958E2 || (bzoj 2151||洛谷P1792) 种树 || 编译优化
https://codeforces.com/contest/958/problem/E2 首先求出N个时刻的N-1个间隔长度,问题就相当于在这些间隔中选K个数,相邻两个不能同时选,要求和最小 方法1 ...
随机推荐
- shell位置参数的遍历
- Spring IOC 的理解,初始化过程
在创建ApplicationContext实例对象过程中会创建一个spring容器,该容器会读取配置文件"cn/wuliaokankan/beans.xml",并统一管理由该文件中 ...
- OAuth_2
角色: OAuth2.0为用户和应用定义了如下角色: 资源拥有者.资源服务器.客户端应用.授权服务器 资源拥有者:拥有共享数据的人或应用,比如Facebook的用户就是 资源拥有者,但资源拥有者也可以 ...
- vue-cli脚手架工具新老版本安装对比
1.老版本 Shift+鼠标右键 选择打开命令窗口 1.创建项目之前,需先确保本机已经安装node 在命令窗口中执行node -v npm -v 2.一般情况下用npm安装东西比较慢,可以使用淘宝 ...
- vue 项目中使用阿里巴巴矢量图标库iconfont
原文:https://www.jianshu.com/p/38262f18eee2 1.打开iconfont阿里巴巴官网https://www.iconfont.cn 2.新建项目(这样方便后期维护图 ...
- Java虚拟机解析篇之---垃圾回收器
上一篇说了虚拟机的内存模型,在说到堆内存的时候我们提到了,堆内存是Java内存中区域最大的一部分,而且垃圾回收器主要就是回收这部分的内容.那么这篇就来介绍一下垃圾回收器的原理以及回收的算法. Java ...
- 在ios微信中提交form,php端收不到参数的问题
今天做h5页面时,微信浏览器中提交form表单,发现php端收不到post过来的参数,在普通浏览器中可以,安卓微信也可以,$_POST,$_GET,$_REQUEST等方式都不行. 后来,把form表 ...
- vue常见面试题
什么是 mvvm? MVVM 是 Model-View-ViewModel 的缩写.mvvm 是一种设计思想.Model 层代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑:View ...
- 【Java架构:基础技术】一篇文章搞掂:MyBatis-Plus
前言 Mybatis:一个流行的半自动ORM框架. Mybatis-Plus:一个Mybatis的增强工具,在Mybatis的基础上只做增强不做改变,为简化开发.提高效率而生. 本文使用的版本:myb ...
- (转)使用OpenGL显示图像(三)绘制Shapes
绘制形状 编写:jdneo - 原文:http://developer.android.com/training/graphics/opengl/draw.html 在定义了使用OpenGL绘制的形状 ...