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 ...
随机推荐
- 数据解压及if else的应用
def sum(items): head, *tails = items return head + sum(tails) if tails else head # 最后一句有点像三目运算符,如果ta ...
- JNI模板
java为了调用底层驱动函数,需要调用外部的C/C++代码,java提供了JNI接口: 然后将C代码编译成库(windows下 .dll / android环境下 .so) arm-linux-gcc ...
- 中国农产品信息网站scrapy-redis分布式爬取数据
---恢复内容开始--- 基于scrapy_redis和mongodb的分布式爬虫 项目需求: 1:自动抓取每一个农产品的详细数据 2:对抓取的数据进行存储 第一步: 创建scrapy项目 创建爬虫文 ...
- Python系列8之socket
目录 socket 简单的聊天机器人 简单的ftp上传 粘包问题的解决 一. socket模块 socket,俗称套接字,其实就是一个ip地址和端口的组合.类似于这样的形式(ip, port),其中 ...
- node session会话
会话机制: 浏览器-->服务器 浏览器<--服务器 (产生一个会话id,保存在cookie中) 浏览器-->服务器(服务器根据会话id关联到相应数据信息体data) var expr ...
- Fabric go sdk初始化所需证书解析
fabric sdk go 提供的官方文档少之又少,要想入门,主要就靠研究官方的e2e系列示例,这真的是一件挺无奈的事情.没法子,只能硬着头皮上了.研究发现,e2e这个例子是通过cryptogen生成 ...
- git将本地项目上传到远程仓库
1.cd mygit 打开项目文件夹 2.git init 初始化git 3.git remote add origin xxx(远程仓库地址) 添加远程库 git remote -v 查看远程 ...
- Linux系统下安装rz/sz命令
执行命令 yum install -y lrzsz rz -be本地上传文件到服务器
- LeetCode:11. ContainerWithWater(Medium)
原题链接:https://leetcode.com/problems/container-with-most-water/description/ 题目要求:给定n个非负整数a1,a2,...,an ...
- cf987f AND Graph
#include <iostream> #include <cstdio> using namespace std; int n, uu, m; bool a[4500005] ...