BZOJ4424/CF19E Fairy(dfs树+树上差分)
即删除一条边使图中不存在奇环。如果本身就是个二分图当然任意一条边都可以,先check一下。否则肯定要删除在所有奇环的交上的边。
考虑怎么找这些边。跑一遍dfs造出dfs树,找出返祖边构成的奇环。可以通过树上差分标记奇环上的边。
但是这显然只包含了一部分奇环。注意到如果某条在奇环上的边同时也在一个偶环上,一定可以找到一个不包含这条边的奇环。并且图中所有其他奇环都是由所找到的奇环加上偶环得到的,所以这就是充分的了。
数据中有重边自环,自环特判一下比较舒服,而任意一条重边都不可能在答案中(本身就是二分图除外)。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
#include<cassert>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 1000010
map<int,int> f[N];
int n,m,p[N],t=-,fa[N<<],deep[N],cnt[][N<<],delta[][N],tot;
struct data{int to,nxt;
}edge[N<<];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void dfs(int k,int from)
{
for (int i=p[k];~i;i=edge[i].nxt)
if (edge[i].to!=from)
if (deep[edge[i].to]&&deep[edge[i].to]<=deep[k])
{
int op=deep[k]-deep[edge[i].to]&;
tot+=op^;cnt[op][i]++;
delta[op][k]++,delta[op][edge[i].to]--;
}
else if (!deep[edge[i].to])
{
deep[edge[i].to]=deep[k]+;
dfs(edge[i].to,k);
}
}
int Count(int op,int k,int from)
{
int s=;
for (int i=p[k];~i;i=edge[i].nxt)
if (edge[i].to!=from&&!deep[edge[i].to])
{
deep[edge[i].to]=deep[k]+;
int d=Count(op,edge[i].to,k);
s+=d,cnt[op][i]+=d;
}
s+=delta[op][k];
return s;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4424.in","r",stdin);
freopen("bzoj4424.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
for (int i=;i<=n*;i++) fa[i]=i;
memset(p,,sizeof(p));
bool flag=;int sc=;
for (int i=;i<=m;i++)
{
int x=read(),y=read();
if (x!=y)
{
f[x][y]++,f[y][x]++;
addedge(x,y);if (x!=y) addedge(y,x);
fa[find(x)]=find(y+n),fa[find(x+n)]=find(y);
if (find(x)==find(y)) flag=;
}
else sc=sc?m+:i;
}
if (sc)
{
if (!flag||sc>m) {cout<<;return ;}
cout<<<<endl<<sc;
return ;
}
if (flag) {cout<<m<<endl;for (int i=;i<=m;i++) printf("%d ",i);return ;}
for (int i=;i<=n;i++) if (!deep[i]) deep[i]=,dfs(i,);
memset(deep,,sizeof(deep));
for (int i=;i<=n;i++) if (!deep[i]) deep[i]=,Count(,i,);
memset(deep,,sizeof(deep));
for (int i=;i<=n;i++) if (!deep[i]) deep[i]=,Count(,i,);
m=;
for (int i=;i<=t;i++) m+=(cnt[][i]==tot)&&(cnt[][i]==)&&(f[edge[i^].to][edge[i].to]==);
cout<<m<<endl;for (int i=;i<=t;i++) if ((cnt[][i]==tot)&&(cnt[][i]==)&&(f[edge[i^].to][edge[i].to]==)) printf("%d ",i/+);
return ;
}
BZOJ4424/CF19E Fairy(dfs树+树上差分)的更多相关文章
- 【BZOJ4424】Cf19E Fairy DFS树
[BZOJ4424]Cf19E Fairy Description 给定 n 个点,m 条边的无向图,可以从图中删除一条边,问删除哪些边可以使图变成一个二分图. Input 第 1 行包含两个整数 n ...
- [BZOJ 4771]七彩树(可持久化线段树+树上差分)
[BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...
- BZOJ4771 七彩树(dfs序+树上差分+主席树)
考虑没有深度限制怎么做.显然的做法是直接转成dfs序上主席树,但如果拓展到二维变成矩形数颜色数肯定没法做到一个log. 另一种做法是利用树上差分.对于同种颜色的点,在每个点处+1,dfs序相邻点的lc ...
- bzoj千题计划229:bzoj4424: Cf19E Fairy
http://www.lydsy.com/JudgeOnline/problem.php?id=4424 图是二分图的条件:没有奇环 所以,如果图不存在奇环,删除任意一条边都可以 如果存在奇环, 对于 ...
- BZOJ2588 主席树 + 树上差分
https://www.lydsy.com/JudgeOnline/problem.php?id=2588 题意:强制在线的询问树链权值第K小(无修) 这种类似于第K小的题,一般容易想到主席树,但是树 ...
- Codechef Sad Pairs——圆方树+虚树+树上差分
SADPAIRS 删点不连通,点双,圆方树 非割点:没有影响 割点:子树DP一下 有不同颜色,所以建立虚树 在圆方树上dfs时候 如果当前点是割点 1.统计当前颜色虚树上的不连通点对,树形DP即可 2 ...
- BZOJ3331 压力 (圆方树+树上差分)
题意 略 题解 求路径上的割点. 然后就直接圆方树上差分 CODE #include <bits/stdc++.h> using namespace std; inline void rd ...
- BZOJ3331 [BeiJing2013]压力[圆方树+树上差分]
圆方树新技能get.具体笔记见图连通性问题学习笔记. 这题求无向图的必经点,这个是一个固定套路:首先,一张连通的无向图中,每对点双和点双之间是以一个且仅一个割点连接起来的(如果超过一个就不能是割点了) ...
- BZOJ4424: Cf19E Fairy
树上差分的代码很简洁,dfs+差分即可 这题很多坑点啊,比如重边自环好坑 #include<cstdio> #include<cstdlib> #include<algo ...
随机推荐
- 用 jQuery 实现表单验证(转载)
jQuery 官方 API 地址: http://api.jquery.com/ 在线引用 jQuery:http://code.jquery.com/ ——选自<锋利的jQuery>(第 ...
- 汇编:将指定的内存中连续N个字节填写成指定的内容
1.loop指令实现 ;=============================== ;循环程序设计 ;将制定内存中连续count个字节填写成指定内容(te) ;loop指令实现 DATAS SEG ...
- Element-ui树形控件el-tree获取父级节点的id
Element-ui官网给的方法 getCheckedKeys() { console.log(this.$refs.tree.getCheckedKeys()); }, 这种只有在所有子级都被选中的 ...
- vue服务端渲染按需引入mint
vue服务器渲染按需引入mint-ui 1.修改.babelrc文件,在.babelrc文件中plugins数组中添加 { "presets": [["es2015&qu ...
- Git 项目提交代码及一些常用命令
在dev_ysg分支 : git add . //把项目添加到仓库 git commit -m "test" // 提交加注释 git push //推到dev_ysg分支上去 g ...
- Sencha Visual Studio(IDE插件)
Sencha Visual Studio(IDE插件) 首先从官网上下载Visual Studio插件,注意不是VSCode编辑器,下载完后安装打开Visual Studio提示你去注册,输入你的se ...
- memcached搭建
MemCache 安装使用 安装memcached之前首先需要安装libevent, 如果没有安装的请自行去安装. 下载memcache http://www.memcached.org/files/ ...
- Python的scrapy之爬取51job网站的职位
今天老师讲解了Python中的爬虫框架--scrapy,然后带领我们做了一个小爬虫--爬取51job网的职位信息,并且保存到数据库中 用的是Python3.6 pycharm编辑器 爬虫主体: im ...
- Kubernetes-创建集群(四)
Kubernetes可以运行在多种平台,从笔记本到云服务商的虚拟机,再到机架上的裸机服务器.要创建一个Kubernetes集群,根据不同的场景需要做的也不尽相同,可能是运行一条命令,也可能是配置自己定 ...
- List排序方法
可用使用Collections.sort(List<T> list)和Collections.sort(List<T> list, Comparator<? super ...