Brief Intro:

给定一个无向图,询问删去哪条边能使得剩下的图为一个二分图,输出所有结果

Algorithm:

关于二分图的重要性质:一个图为二分图的充要条件为其中没有奇环

1、如果没有奇环,那么删去任何一条边都不会使其变为奇环

2、如果存在一个或多个奇环,删去的边必为所有奇环的一条公共边

   但这样仍然无法保证残余图是一个二分图:因为有偶环的存在

为了寻找奇环或者偶环,我们一般采取dfs树的方式

我们可以证明(奇偶性判断即可)当一个环上有两个偶返祖边或两个奇返祖边时,这个环必为偶环

而当一个环上有一个奇返祖边以及一个偶返祖边时,这个环必为奇环

如果一条边有一个奇环以及一个偶环通过,那么删去这条边后一定会出现一个环中包含一个奇返祖边和一个偶返祖边

从而出现奇环,不成立

题目被转化为:求出既是所有奇环公共边又不在任何一个偶环中的边

dfs树维护每条边经过的奇/偶环个数即可

Code:

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> P;
typedef long long ll;
#define F first
#define S second const int MAXN=1e4+;
int n,m,odd[MAXN],even[MAXN],vis[MAXN],match[MAXN],col[MAXN],st,cnt;
vector<P> G[MAXN];
vector<int> res; void dfs(int cur,int anc)
{
vis[cur]=;col[cur]=col[anc]^;
for(int i=;i<G[cur].size();i++)
{
P t=G[cur][i];
if(t.F==anc) continue;
if(!vis[t.F]) //将点和其父边配对
match[t.F]=t.S,dfs(t.F,cur),odd[cur]+=odd[t.F],even[cur]+=even[t.F];
else if(vis[t.F]==)
col[cur]==col[t.F]?odd[cur]++,st=t.S,cnt++:even[cur]++;
else
col[cur]==col[t.F]?odd[cur]--:even[cur]--; //如果到了一个环的起始点,那么该点的父边不在环中
}
vis[cur]=-; //不同的标记
} int main()
{
cin >> n >> m;
for(int i=;i<=m;i++)
{
int x,y;cin >> x >> y;
G[x].push_back(P(y,i));G[y].push_back(P(x,i));
} for(int i=;i<=n;i++)
if(!vis[i])
dfs(i,); if(cnt==)
for(int i=;i<=m;i++) res.push_back(i);
else
{
if(cnt==) res.push_back(st); //如果只有一个奇环,起始边也符合条件
for(int i=;i<=n;i++)
if(odd[i]==cnt && !even[i]) res.push_back(match[i]);
sort(res.begin(),res.end());
} cout << res.size() << endl;
for(int i=;i<res.size();i++)
cout << res[i] << " "; return ;
}

Review:

1、二分图的充要条件:不含奇环

同时不用考虑原图中的所有环,而只要考虑dfs树构造出的环即可

2、可采用dfs树的方式计算图中的奇、偶环

注意对一个环起始点的特殊处理

(UPD:实际上这是一个$dfs$树上差分的过程)

3、由于dfs树的无后效性,如果一个大环中包含两条返祖边,去掉两小环的公共路径*2,不改变两小环总和的奇偶性,从而能推断出大环的奇偶性

利用dfs树中的迭代性、公共路径推出有用的结论

4:注意很多时候只要考虑$dfs$返祖边的环即可!!!!

[Codeforces 19E] Fiary的更多相关文章

  1. bzoj 4424: Cf19E Fairy && codeforces 19E. Fairy【树形dp】

    参考:https://blog.csdn.net/heheda_is_an_oier/article/details/51131641 这个找奇偶环的dp1真是巧妙,感觉像tarjan一样 首先分情况 ...

  2. Codeforces 19E 树上差分

    思路: 先随便建出来一棵搜索树(图可能不连通?) 每一条非树边(剩下的边)和树边都可以构成一个环. 我们只看一个非树边和某些树边构成的这些环. 分成三种情况: 1.没有奇环  所有边都可以删 2.有一 ...

  3. Codeforces 19E&BZOJ 4424 Fairy(好题)

    日常自闭(菜鸡qaq).不过开心的是看了题解之后1A了.感觉这道题非常好,必须记录一下,一方面理清下思路,一方面感觉自己还没有完全领会到这道题的精髓先记下来以后回想. 题意:给定 n 个点,m 条边的 ...

  4. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  5. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  6. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  7. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  8. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

  9. CodeForces - 274B Zero Tree

    http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...

随机推荐

  1. 安卓下拉刷新空间SwipeRefreshLayout的基本使用

    1.先写布局文件 <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/refresh" androi ...

  2. PHP代码优化小笔记

    1.十万级以上次执行情况,方法可以被静态化,考虑声明为静态.html静态页面速度更快 2.echo 替换print:echo时逗号连接符替换点号连接符 3.循环之前设置循环最大次数,循环参数不要使用函 ...

  3. javascript简易下拉菜单效果

    JS代码: window.onload=function(){ var oDiv=document.getElementById('navMenu'); var aUl=oDiv.getElement ...

  4. shell之流程控制

    一.if语句.while.for循环各种小例题 1.用户验证 [root@bogon ~]# cat buer.sh #!/bin/bash #user='buer' #password='1234. ...

  5. 【Foreign】划分序列 [线段树][DP]

    划分序列 Time Limit: 20 Sec  Memory Limit: 256 MB Description Input Output 仅一行一个整数表示答案. Sample Input 9 4 ...

  6. 将setter方法与itemClick: 进行类比

        https://www.evernote.com/shard/s227/sh/a0c3afa3-8792-4756-8594-d2387a7f57ad/b561ff665af9ad401c8e ...

  7. autoKeras入门

    测试本地mnist数据集 图片只用500张,450张做train与50张test, 代码如下: # conding:utf-8 import os os.environ[' import numpy ...

  8. bzoj 1500 修改区间 splay

    内个我也不知道哪儿不对,TLE了,说说思路吧 其实思路也没什么说的,就是裸的splay,对于最后一个操作 我们记下每个区间的最长前缀,最长后缀,那么最长子序列就是 前缀,后缀,左子树的后缀+右子树的前 ...

  9. springcloud+eureka简单入门案例

    springcloud+eureka简单入门案例 一.服务提供者 直接提供服务,入门案例没有特别要设置的地方,注意下端口,由于要启动多个服务,可能会冲突 配置文件(src/main/resources ...

  10. 【 Linux 】Linux套接字简要说明

    Linux套接字    源IP地址和目的IP地址以及源端口和目标端口号的组合称为套接字.其作用于标识客户端请求的服务器和服务. 套接字,支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间 ...