P3731 二分图匹配必经边

题意经过一番转换变成了 让你在一个二分图上删一条边使得二分图的最大独立集大小至少+1
二分图的最大独立集=点数-最小点覆盖(最大匹配) 点数是固定不变的 所以我们要减少最大匹配数
则删掉的哪一条边必须是二分图匹配里必须的一条边
做法:先Dinic跑一次 然后Tarjan缩点 找到图中端点不为S/T且满流的边 再判两端点是否属于一个SCC
如果属于一个SCC则必定存在另一个边可以替换掉这条匹配边
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 10100
#define MAXM 150150
#define inf 1e9
inline int read()
{
int x=;bool t=false;char ch=getchar();
while((ch<''||ch>'')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<=''&&ch>='')x=x*+ch-,ch=getchar();
return t?-x:x;
}
struct Line{int v,next,w;}e[MAXM<<];
int h[MAXN],cnt=;
inline void Add(int u,int v,int w)
{
e[cnt]=(Line){v,h[u],w};h[u]=cnt++;
e[cnt]=(Line){u,h[v],};h[v]=cnt++;
}
int S,T,level[MAXN];
bool bfs()
{
for(int i=S;i<=T;++i)level[i]=;
queue<int> Q;level[S]=;Q.push(S);
while(!Q.empty())
{
int u=Q.front();Q.pop();
for(int i=h[u];i;i=e[i].next)
if(e[i].w&&!level[e[i].v])
level[e[i].v]=level[u]+,Q.push(e[i].v);
}
return level[T];
}
int cur[MAXN];
int dfs(int u,int flow)
{
if(u==T||!flow)return flow;
int ret=;
for(int &i=cur[u];i;i=e[i].next)
{
int v=e[i].v,d;
if(e[i].w&&level[v]==level[u]+)
{
d=dfs(v,min(flow,e[i].w));
ret+=d;flow-=d;
e[i].w-=d;e[i^].w+=d;
if(!flow)break;
}
}
if(!ret)level[u]=;
return ret;
}
int Dinic()
{
int ret=;
while(bfs())
{
for(int i=S;i<=T;++i)cur[i]=h[i];
ret+=dfs(S,inf);
}
return ret;
}
vector<pair<int,int> > Ans;
vector<int> E[MAXN];
int n,m,col[MAXN];
void pre(int u,int c){col[u]=c;for(int v:E[u])if(!col[v])pre(v,c^);}
int dfn[MAXN],low[MAXN],tim,G[MAXN],gr;
int St[MAXN],top;bool ins[MAXN];
void Tarjan(int u)
{
dfn[u]=low[u]=++tim;St[++top]=u;ins[u]=true;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(!e[i].w)continue;
if(!dfn[v])Tarjan(v),low[u]=min(low[u],low[v]);
else if(ins[v])low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
++gr;int v;
do{v=St[top--];G[v]=gr;ins[v]=false;}while(u!=v);
}
}
int main()
{
n=read();m=read();
for(int i=;i<=m;++i)
{
int u=read(),v=read();
E[u].push_back(v);
E[v].push_back(u);
}
for(int i=;i<=n;++i)if(!col[i])pre(i,);
S=;T=n+;
for(int i=;i<=n;++i)
if(col[i]==)
{
Add(S,i,);
for(int v:E[i])Add(i,v,);
}
else Add(i,T,);
int ret=Dinic();
for(int i=S;i<=T;++i)if(!dfn[i])Tarjan(i);
for(int u=;u<=n;++u)
if(col[u]==)
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(e[i].w)continue;
if(v==S||v==T)continue;
if(G[u]!=G[v])Ans.push_back(u<v?make_pair(u,v):make_pair(v,u));
}
sort(Ans.begin(),Ans.end());
printf("%d\n",(int)Ans.size());
for(auto a:Ans)printf("%d %d\n",a.first,a.second);
return ;
}
P3731 二分图匹配必经边的更多相关文章
- UVA 12549 - 二分图匹配
题意:给定一个Y行X列的网格,网格种有重要位置和障碍物.要求用最少的机器人看守所有重要的位置,每个机器人放在一个格子里,面朝上下左右四个方向之一发出激光直到射到障碍物为止,沿途都是看守范围.机器人不会 ...
- POJ 1274 裸二分图匹配
题意:每头奶牛都只愿意在她们喜欢的那些牛栏中产奶,告诉每头奶牛愿意产奶的牛棚编号,求出最多能分配到的牛栏的数量. 分析:直接二分图匹配: #include<stdio.h> #includ ...
- BZOJ1433 ZJOI2009 假期的宿舍 二分图匹配
1433: [ZJOI2009]假期的宿舍 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2375 Solved: 1005[Submit][Sta ...
- HDU1281-棋盘游戏-二分图匹配
先跑一个二分图匹配,然后一一删去匹配上的边,看能不能达到最大匹配数,不能这条边就是重要边 /*----------------------------------------------------- ...
- HDU 1083 网络流之二分图匹配
http://acm.hdu.edu.cn/showproblem.php?pid=1083 二分图匹配用得很多 这道题只需要简化的二分匹配 #include<iostream> #inc ...
- hdu 5727 Necklace dfs+二分图匹配
Necklace/center> 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5727 Description SJX has 2*N mag ...
- BZOJ 1059 & 二分图匹配
题意: 判断一个黑白染色的棋盘能否通过交换行或列使对角线上都是黑色. SOL: 真是有点醉...这种问题要么很神要么很水...第一眼感觉很水但就是不造怎么做...想了10分钟怎么感觉就是判断个数够不够 ...
- 【POJ 3020】Antenna Placement(二分图匹配)
相当于用1*2的板覆盖给定的h*w的格子里的点,求最少的板.可以把格子相邻的分成两个集合,如下图,0为一个集合,1的为一个,也就是(行数+列数)为奇数的是一个集合,为偶数的为另一个集合.1010101 ...
- BZOJ-1143&&BZOJ-2718 祭祀river&&毕业旅行 最长反链(Floyed传递闭包+二分图匹配)
蛋蛋安利的双倍经验题 1143: [CTSC2008]祭祀river Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1901 Solved: 951 ...
随机推荐
- Visual Studio Code的设置及插件同步
Visual Studio Code的设置及插件同步 使用Visual Studio Code开发有一段时间了,用起来是极其的顺手,但是唯独一点不爽的就是,Visual Studio Code不像Vi ...
- mybatis resultMap 子元素
resultMap constructor - 类在实例化时,用来注入结果到构造方法中 idArg - ID 参数;标记结果作为 ID 可以帮助提高整体效能 arg - 注入到构造方法的一个普通结果 ...
- 【AMAD】django-countries -- 为Django app的form提供country选项,为model提供CountryField
动机 简介 个人评分 动机 有时候看一些数据库设计,国家数据会存在一个单独的表里面.这种方式读取数据库无疑又要加上一层join,很不划算. 简介 [django-countries]1解决的是: 不用 ...
- C++进阶笔记
思想原则: 以类为例,类最终要处理的是数据,方法只是过程,最终要改变的是private中的数据成员状态.程序设计也是如此,要的是数据. 一.const的作用 const定义变量:定义了一个不可修改的常 ...
- 手把手教你用原始方式上传项目至GitHub
小编GitHub:https://github.com/ds1889 首先你得注册一个自己的GitHub账号,注册网址:https://github.com/join 有了自己的账号以后,就可以进行登 ...
- js-object引用示例
function displayInfo(args){ var output=""; if(typeof args.name == "string"){ out ...
- Java-Redis Serializable序列化
在Java中使用redis存储User对象时,进行JUnit测试时,控制台: 2019-06-24 16:56:45.520 INFO 27688 --- [ main] j.LocalContain ...
- [转帖]判断Linux进程在哪个CPU核运行的方法
判断Linux进程在哪个CPU核运行的方法 原文网址:http://www.embeddedlinux.org.cn/html/xinshourumen/201601/30-5013.html 问 ...
- 有关java5以后的线程
创建线程的方式 方式一 继承于Thread类 /** * 多线程的创建,方式一:继承于Thread类 * 1. 创建一个继承于Thread类的子类 * 2. 重写Thread类的run() --> ...
- SpringBoot起飞系列-国际化(六)
一.前言 国际化这个功能可能我们不常用,但是在有需要的地方还是必须要上的,今天我们就来看一下怎么在我们的web开发中配置国际化,让我们的网站可以根据语言来展示不同的形式.本文接续上一篇SpringBo ...