题意经过一番转换变成了 让你在一个二分图上删一条边使得二分图的最大独立集大小至少+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=0;bool t=false;char ch=getchar();while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();if(ch=='-')t=true,ch=getchar();while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();return t?-x:x;
}
struct Line{int v,next,w;}e[MAXM<<1];
int h[MAXN],cnt=2;
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],0};h[v]=cnt++;
}
int S,T,level[MAXN];
bool bfs()
{for(int i=S;i<=T;++i)level[i]=0;queue<int> Q;level[S]=1;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]+1,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=0;for(int &i=cur[u];i;i=e[i].next){int v=e[i].v,d;if(e[i].w&&level[v]==level[u]+1){d=dfs(v,min(flow,e[i].w));ret+=d;flow-=d;e[i].w-=d;e[i^1].w+=d;if(!flow)break;}}if(!ret)level[u]=0;return ret;
}
int Dinic()
{int ret=0;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^1);}
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=1;i<=m;++i){int u=read(),v=read();E[u].push_back(v);E[v].push_back(u);}for(int i=1;i<=n;++i)if(!col[i])pre(i,2);S=0;T=n+1;for(int i=1;i<=n;++i)if(col[i]==2){Add(S,i,1);for(int v:E[i])Add(i,v,1);}else Add(i,T,1);int ret=Dinic();for(int i=S;i<=T;++i)if(!dfn[i])Tarjan(i);for(int u=1;u<=n;++u)if(col[u]==2)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 0;
}

转载于:https://www.cnblogs.com/Aragaki/p/10605852.html

P3731 二分图匹配必经边相关推荐

  1. Dinic二分图匹配 || Luogu P3386

    题面:[模板]二分图匹配 思路:Dinic实现二分图匹配,要建一个超级源点(S)和超级汇点(T),分别定为N+M+1和N+M+2 然后S去和N中的数建正边和反边,正边权值为1,反边权值为0:M中的数去 ...

  2. 二分图匹配匈牙利算法DFS实现

    1 /*==================================================*\ 2 | 二分图匹配(匈牙利算法DFS 实现) 3 | INIT: g[][]邻接矩阵; ...

  3. poj1274(二分图匹配)

    (一道基础的二分图匹配) 题目意思大概为N个牛和M个栅栏,一个牛和一个栅栏只能匹配一次,求最大匹配 直接套用二分图最大匹配模板即可 #include <iostream> #include ...

  4. poj2724(二分图匹配)

    题目大概意思为有部分奶酪需要处理,若两个奶酪的二进制只有一位不同,则可以一起处理,问最少需要处理几次 题目思路: 将可以一起处理的两个奶酪用边连接在一起,相当于边只连接二进制中有偶数个1的奶酪和二进制 ...

  5. 算法模板——二分图匹配

    实现功能为二分图匹配 原理:匈牙利算法,核心思想--匹配上了就配,没直接匹配上也要通过前面的腾出位置让这个匹配上(详见:趣写算法系列之--匈牙利算法) 本程序以Codevs2776为例 详见Codev ...

  6. 算法:ACM二分图匹配 HDU2063

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2063 摘录于互联网,原创作者redraiment,很详细的二分图匹配入门资料! 2063 过山车 Pr ...

  7. BZOJ1433 [ZJOI2009]假期的宿舍 - 二分图匹配

    题解 一道裸的二分图匹配,稍微有一点细节需要注意, 但是非常裸= = 本校并且住校的向自己的床和 自己认识的并且本校的人的床连边 离校的不需要向外连边 不是本校的就和自己认识的 并且是本校的人的床连边 ...

  8. POJ2536 二分图匹配

    题意:      有n只老鼠,m个洞,每个洞最多可以藏一只老鼠,每个老鼠的移动速度都是v,给你他们的当前坐标,和洞的坐标,突然老鹰来了,他们必须在s秒内跑到一个洞藏起来,问你最少有多少只老鼠被抓走了. ...

  9. URAL 1721 Two Sides of the Same Coin(二分图匹配,输出匹配对象)

    题意:给出n个人的信息,名字.特征.排名. 在排名相差2的前提下,特征为testdata可以与特征为statements的组队,特征为anything可以任何一人组队: 求最多匹配对数,并将每队名字输 ...

最新文章

  1. android setContentView()
  2. 2020年智能家居市场规模将达到3576亿元
  3. LeetCode 1030. 距离顺序排列矩阵单元格(排序Lambda表达式BFS)
  4. 安卓DialogFragment如何使用?
  5. [解读REST] 6.REST的应用经验以及教训
  6. app提示已到期_安装软件时,显示软件证书过期,怎么回事?
  7. win7自带计算机,win7系统自带的计算器不见了的解决方法
  8. 烙铁使用注意事项及元器件件焊接要点
  9. java中的Cipher类
  10. mac版 IGV(版本2.12.3)安装
  11. rust编程语言排名_Rust语言在堆栈溢出调查中排名最高
  12. python中num函数是什么意思_如何理解python3函数中num的用法?
  13. Photoshop cs8 颜色 查看调出 hsb模式滑块
  14. [转]一个女孩的IT创业经历,男人女人必看! 第二部分
  15. SnapMotion for Mac(视频截图工具)
  16. 计算机毕业设计Python+uniapp+安卓移动LYQ电子商城APP(WEB+APP+LW)
  17. jmeter阶梯式加压测试小笔记
  18. Redis 键值设计使用总结
  19. PC市场份额快速回升,荣耀欲挑战苹果华为?
  20. 火狐浏览器 使用五笔输入法无法输入数字

热门文章

  1. Linux基础命令---killall
  2. 计算机网络实验3:网络设备基本配置
  3. openstack+essex+quantum成功show
  4. Django创建项目
  5. 基于Netty的http服务器
  6. Cocos2d-x V3.2+Cocos Studio1.6 实现一个简单的uibutton点击功能
  7. Centos 开放端口
  8. 每周一荐:foobar2000, 奇幻人生, 一个Flash小游戏
  9. category android:name=android.intent.category.DEFAULT / 惹的祸
  10. android 弹出对话框时显示键盘