<题目链接>

题目大意:

给你n个点和m条边,每条边代表两点具有匹配关系,问你有多少对匹配是冗余的。

解题分析:

所谓不冗余,自然就是这对匹配关系处于最大匹配中,即该匹配关系有意义。那怎样判断该匹配是否在最大匹配中呢?我们可以枚举每一对匹配,然后对其进行取消其匹配关系,对其余的匹配跑一遍最大匹配,如果是原始最大匹配-1,说明这对匹配关系在最大匹配关系中。需要注意的是,删除匹配关系的时候,不经要将该边的匹配关系删除,还需将所有点与这两点之间的匹配关系删除(即相当于删除这两点)。

 #include <iostream>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define MAXN 310
#define CLR(a,b) memset(a,b,sizeof(a))
deque<int> Q;
//g[i][j]存放关系图:i,j是否有边,match[i]存放i所匹配的点
bool g[MAXN][MAXN],inque[MAXN],inblossom[MAXN];
int match[MAXN],pre[MAXN],base[MAXN]; //找公共祖先
int findancestor(int u,int v)
{
bool inpath[MAXN]={false};
while()
{
u=base[u];
inpath[u]=true;
if(match[u]==-)break;
u=pre[match[u]];
}
while()
{
v=base[v];
if(inpath[v])return v;
v=pre[match[v]];
}
} //压缩花
void reset(int u,int anc)
{
while(u!=anc)
{
int v=match[u];
inblossom[base[u]]=;
inblossom[base[v]]=;
v=pre[v];
if(base[v]!=anc)pre[v]=match[u];
u=v;
}
} void contract(int u,int v,int n)
{
int anc=findancestor(u,v);
CLR(inblossom,);
reset(u,anc);reset(v,anc);
if(base[u]!=anc)pre[u]=v;
if(base[v]!=anc)pre[v]=u;
for(int i=;i<=n;i++)
if(inblossom[base[i]])
{
base[i]=anc;
if(!inque[i])
{
Q.push_back(i);
inque[i]=;
}
}
} bool dfs(int S,int n)
{
for(int i=;i<=n;i++)pre[i]=-,inque[i]=,base[i]=i;
Q.clear();Q.push_back(S);inque[S]=;
while(!Q.empty())
{
int u=Q.front();Q.pop_front();
for(int v=;v<=n;v++)
{
if(g[u][v]&&base[v]!=base[u]&&match[u]!=v)
{
if(v==S||(match[v]!=-&&pre[match[v]]!=-))contract(u,v,n);
else if(pre[v]==-)
{
pre[v]=u;
if(match[v]!=-)Q.push_back(match[v]),inque[match[v]]=;
else
{
u=v;
while(u!=-)
{
v=pre[u];
int w=match[v];
match[u]=v;
match[v]=u;
u=w;
}
return true;
}
}
}
}
}
return false;
} int solve(int n)
{
CLR(match,-);
int ans=;
for(int i=;i<=n;i++)
if(match[i]==-&&dfs(i,n))
ans++;
return ans;
}
/*-- 以上为带花树求一般图最大匹配的模板 --*/
bool vis[];
int a[],b[];
int main() {
int n , m;
while(scanf("%d%d",&n,&m) != EOF) {
CLR(g,false);CLR(vis,false);
for(int i = ; i <= m; i++) {
scanf("%d%d",&a[i],&b[i]);
g[a[i]][b[i]] = g[b[i]][a[i]] = true;
}
int ans = solve(n);
vector<int> vec;
for(int i = ; i <= m; i++) { //枚举不进行匹配边
int x = a[i] , y = b[i];
CLR(g,false); //清空匹配关系,接下来进行重置
for(int j = ; j <= m; j++) if(i!=j){
int tmp1 = a[j] , tmp2 = b[j];
if(tmp1==x||tmp1==y||tmp2==x||tmp2==y)continue; //为什么是将所有包含这两点之间匹配关系的全部(即删除点)清除 ???
g[tmp1][tmp2] = g[tmp2][tmp1] = true;
}
int tmp = solve(n);
if(tmp != ans - ) { //如果删除这条边后,最大匹配数不是原始值-1,说明这条边不在最大匹配中
vec.push_back(i);
}
}
printf("%d\n",vec.size());
if(vec.size()>) {
printf("%d",vec[]);
for(int i = ; i < vec.size(); i++) {
printf(" %d",vec[i]);
}
}
puts("");
}
return ;
}

2018-11-19

HDU 4687 Boke and Tsukkomi (一般图最大匹配)【带花树】的更多相关文章

  1. HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力

    一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 假设C2+2==C1则这条边再某个最大匹配中 Boke and ...

  2. HDU 4687 Boke and Tsukkomi 一般图匹配,带花树,思路,输出注意空行 难度:4

    http://acm.hdu.edu.cn/showproblem.php?pid=4687 此题求哪些边在任何一般图极大匹配中都无用,对于任意一条边i,设i的两个端点分别为si,ti, 则任意一个极 ...

  3. ZOJ 3316 Game 一般图最大匹配带花树

    一般图最大匹配带花树: 建图后,计算最大匹配数. 假设有一个联通块不是完美匹配,先手就能够走那个没被匹配到的点.后手不论怎么走,都必定走到一个被匹配的点上.先手就能够顺着这个交错路走下去,最后一定是后 ...

  4. HDU 4687 Boke and Tsukkomi (一般图匹配带花树)

    Boke and Tsukkomi Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Othe ...

  5. 【learning】一般图最大匹配——带花树

    问题描述 ​ 对于一个图\(G(V,E)\),当点对集\(S\)满足任意\((u,v)\in S\),均有\(u,v\in V,(u,v)\in E\),且\(S\)中没有点重复出现,我们称\(S\) ...

  6. UOJ #79 一般图最大匹配 带花树

    http://uoj.ac/problem/79 一般图和二分图的区别就是有奇环,带花树是在匈牙利算法的基础上对奇环进行缩点操作,复杂度似乎是O(mn)和匈牙利一样. 具体操作是一个一个点做类似匈牙利 ...

  7. hdu 4687 Boke and Tsukkomi

    Dancing link twice. Find the maximum combination numbers in the first time. Enumerate each node, dan ...

  8. 【UOJ 79】 一般图最大匹配 (✿带花树开花)

    从前一个和谐的班级,所有人都是搞OI的.有 n 个是男生,有 0 个是女生.男生编号分别为 1,…,n. 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人负责吐槽.每个人至多属于 ...

  9. 【UOJ #79】一般图最大匹配 带花树模板

    http://uoj.ac/problem/79 带花树模板,做法详见cyb的论文或fhq的博客. 带花树每次对一个未盖点bfs增广,遇到奇环就用并查集缩环变成花(一个点),同时记录每个点的Next( ...

随机推荐

  1. deepin 桌面突然卡死

    deepin桌面突然卡死 使用快捷键Ctrl+alt+F2 重启systemctl

  2. mvc 模式和mtc 模式的区别

    首先说说Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的.松耦合的方式连接在一起,模型负责业务对象与数据库的映射( ...

  3. js----常用功能

    切割 1. a="ddd" a.substr(0,1) 通过js找子代 document.getElementByClass("ddd").getElement ...

  4. 3种vue路由传参的基本模式

    路由是连接各个页面的桥梁,而参数在其中扮演者异常重要的角色,在一定意义上,决定着两座桥梁是否能够连接成功. 在vue路由中,支持3中传参方式. 场景,点击父组件的li元素跳转到子组件中,并携带参数,便 ...

  5. SpringMvc框架MockMvc单元测试注解及其原理分析

    来源:https://www.yoodb.com/ 首先简单介绍一下Spring,它是一个轻量级开源框架,简单的来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开 ...

  6. 目标检测算法之YOLOv3

    参考地址:https://blog.csdn.net/leviopku/article/details/82660381 YOLO v3结构图 DBL:卷积+BN+leaky relu,是v3的最小组 ...

  7. MongoDB 入门

    1 MongoDb 简介 MongoDB是为互联网而生的数据库,是文档数据库. 1.1 优点: Schema-less,不需要预先定义表结构,同一个"表"中可以保存多个格式的数据: ...

  8. 原生开发小程序 和 wepy 、 mpvue, Taro 对比

    https://blog.csdn.net/yang450712123/article/details/79623518 mpvue https://www.cnblogs.com/bgwhite/p ...

  9. Go语言之defer关键字

    类似于java中的finally, 在函数返回来执行, 它用来保证函数一定会作一些事情. package main import "fmt" func main() { defer ...

  10. webpack学习笔记--配置plugins

     Plugin Plugin 用于扩展 Webpack 功能,各种各样的 Plugin 几乎让 Webpack 可以做任何构建相关的事情. 配置 Plugin Plugin 的配置很简单, plugi ...