Strategic game(无向?)二分图最小点覆盖(Poj1463,Uva1292)
原题链接
此题求二分图的最小点覆盖,数值上等于该二分图的最大匹配。得知此结论可以将图染色,建有向图,然后跑匈牙利/网络流,如下。然而...
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=2000+5;
int q[MAXN],hd1[MAXN],hd2[MAXN];
int lnk[MAXN];
bool vis[MAXN],bw[MAXN];
int n,ft,rr,cnt1,cnt2;
struct Edge
{
int t,n;
}e1[MAXN<<1],e2[MAXN<<1];
inline void build(int f,int t)
{
e1[++cnt1]=(Edge){t,hd1[f]};
hd1[f]=cnt1;
}
inline void build2(int f,int t)
{
e2[++cnt2]=(Edge){t,hd2[f]};
hd2[f]=cnt2;
}
void bfs()
{
ft=rr=0;
memset(bw,0,sizeof bw);
memset(vis,0,sizeof vis);
q[rr++]=0;
vis[0]=1;
bw[0]=1;
while(ft<rr)
{
int u=q[ft++];
for(int i=hd1[u];i;i=e1[i].n)
{
int v=e1[i].t;
if(!vis[v])
{
vis[v]=1;
bw[v]=bw[u]^1;
q[rr++]=v;
}
}
}
}
bool match(int u)
{
for(int i=hd2[u];i;i=e2[i].n)
{
int v=e2[i].t;
if(!vis[v])
{
vis[v]=1;
if(lnk[v]==-1||match(lnk[v]))
{
lnk[v]=u;
return 1;
}
}
}
return 0;
}
int main()
{
while(~scanf("%d",&n))
{
cnt1=cnt2=0;
memset(hd1,0,sizeof hd1);
memset(e1,0,sizeof e1);
memset(e2,0,sizeof e2);
memset(hd2,0,sizeof hd2);
memset(lnk,-1,sizeof lnk);
int from,m,to;
for(int i=0;i<n;++i)
{
scanf("%d:(%d)",&from,&m);
for(int i=1;i<=m;++i)
scanf("%d",&to),build(from,to),build(to,from);
}
bfs();
for(int k=0;k<n;++k)
{
if(bw[k])
{
for(int i=hd1[k];i;i=e1[i].n)
build2(k,e1[i].t);
}
}
int ans=0;
for(int i=0;i<n;++i)
{
if(bw[i])
{
memset(vis,0,sizeof vis);
if(match(i))
++ans;
}
}
printf("%d\n",ans);
}
return 0;
}
然而我看网络上流传的都是另一种做法,直接输出在原无向图的最大匹配除以2,却很少有人证明(可能是各位大佬都认为这太显然了不用证)。仔细思考这个结论还是比较显然的(虽然我还想了一会),这里给出简单的证明,原来匹配一次的边被分别从从左右两个方向匹配了一次,这样每天匹配边就被记录了两次,又因为是求得的是最大匹配数,所以左右两边的匹配都应是最大匹配,故求给定无向图求最大匹配可以直接在原图求最大匹配,答案为该数值除以2。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=2000+5;
int hd[MAXN],lnk[MAXN];
bool vis[MAXN];
int n,cnt;
struct Edge
{
int t,n;
}e[MAXN<<1];
inline void build(int f,int t)
{
e[++cnt]=(Edge){t,hd[f]};
hd[f]=cnt;
}
bool match(int u)
{
for(int i=hd[u];i;i=e[i].n)
{
int v=e[i].t;
if(!vis[v])
{
vis[v]=1;
if(lnk[v]==-1||match(lnk[v]))
{
lnk[v]=u;
return 1;
}
}
}
return 0;
}
int main()
{
while(~scanf("%d",&n))
{
cnt=0;
memset(hd,0,sizeof hd);
memset(e,0,sizeof e);
memset(lnk,-1,sizeof lnk);
int from,m,to;
for(int i=0;i<n;++i)
{
scanf("%d:(%d)",&from,&m);
for(int i=1;i<=m;++i)
scanf("%d",&to),build(from,to),build(to,from);
}
int ans=0;
for(int i=0;i<n;++i)
{
memset(vis,0,sizeof vis);
if(match(i))
++ans;
}
printf("%d\n",ans>>1);
}
return 0;
}
还有DP解法,待填。
11.02UPD 树形DP解法
Strategic game(无向?)二分图最小点覆盖(Poj1463,Uva1292)的更多相关文章
- HihoCoder1127 二分图三·二分图最小点覆盖和最大独立集
二分图三·二分图最小点覆盖和最大独立集 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上次安排完相亲之后又过了挺长时间,大家好像都差不多见过面了.不过相亲这个事不是说 ...
- hihoCoder #1127 : 二分图二·二分图最小点覆盖和最大独立集
#1127 : 二分图二·二分图最小点覆盖和最大独立集 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 在上次安排完相亲 ...
- Asteroids POJ - 3041 二分图最小点覆盖
Asteroids POJ - 3041 Bessie wants to navigate her spaceship through a dangerous asteroid field in ...
- POJ2226 Muddy Fields(二分图最小点覆盖集)
题目给张R×C的地图,地图上*表示泥地..表示草地,问最少要几块宽1长任意木板才能盖住所有泥地,木板可以重合但不能盖住草地. 把所有行和列连续的泥地(可以放一块木板铺满的)看作点且行和列连续泥地分别作 ...
- POJ1325 Machine Schedule(二分图最小点覆盖集)
最小点覆盖集就是在一个有向图中选出最少的点集,使其覆盖所有的边. 二分图最小点覆盖集=二分图最大匹配(二分图最大边独立集) 这题A机器的n种模式作为X部的点,B机器的m种模式作为Y部的点: 每个任务就 ...
- hihoCoder #1127:二分图最小点覆盖和最大独立集
题目大意:求二分图最小点覆盖和最大独立集. 题目分析:如果选中一个点,那么与这个点相连的所有边都被覆盖,使所有边都被覆盖的最小点集称为最小点覆盖,它等于最大匹配:任意两个点之间都没有边相连的最大点集称 ...
- [POJ] 2226 Muddy Fields(二分图最小点覆盖)
题目地址:http://poj.org/problem?id=2226 二分图的题目关键在于建图.因为“*”的地方只有两种木板覆盖方式:水平或竖直,所以运用这种方式进行二分.首先按行排列,算出每个&q ...
- 二分图 最小点覆盖 poj 3041
题目链接:Asteroids - POJ 3041 - Virtual Judge https://vjudge.net/problem/POJ-3041 第一行输入一个n和一个m表示在n*n的网格 ...
- 四川第七届 D Vertex Cover(二分图最小点覆盖,二分匹配模板)
Vertex Cover frog has a graph with nn vertices v(1),v(2),…,v(n)v(1),v(2),…,v(n) and mm edges (v(a1), ...
随机推荐
- P2048 [NOI2010]超级钢琴 [堆+st表]
考虑只能取长度为 [L,R] 的,然后不难想到用堆搞. 搞个前缀和的st表,里面维护的是一个 最大值的位置 struct rmq { int mx[N][20] ; void qwq(int n) { ...
- 《操作系统真象还原》MBR
以下是读本书第三章的收获. 如何知道一个源程序的各符号(指令和变量)地址?简单来说,地址就是该符号偏移文件开头的距离,符号的地址是按顺序编排的,所以两个相邻的符号,其地址也是相邻的.对于指令来说,指令 ...
- CF1299D Around the World
题意 \(n\)阶无向图,\(m\)条带权边,保证\(1\)不会被"超过\(3\)阶的圈"所包含.求删除与\(1\)相邻的边集,使得不存在从\(1\)出发的权值为\(0\)的非平凡 ...
- HDFS的扩容
一.扩容 1.1横向扩容:加节点 https://www.cnblogs.com/the-roc/p/12362926.html 1.2纵向扩容:加硬盘 二.纵向扩容 2.1添加硬盘 2.2在关 ...
- 126.自动处理上传的文件,获取上传文件的url
使用模型来处理上传的文件: 在定义模型的时候,我们可以给存储的文件的字段指定为FileField,这个field可以传递一个upload_to参数,用来指定上传上来的文件保存到哪里,比如我们让它保存到 ...
- JS 字符串 String对象
charAt(index) 返回指定索引位置的字符 charCodeAt() 返回指定索引位置字符的 Unicode 值 indexOf(searchString, startIndex) 返回子字符 ...
- Java实现的上传并压缩图片功能【可等比例压缩或原尺寸压缩】
本文实例讲述了Java实现的上传并压缩图片功能.分享给大家供大家参考,具体如下: 先看效果: 原图:1.33M 处理后:27.4kb 关键代码: package codeGenerate.util; ...
- 用windows 画图 裁剪照片
图片大小432*312 1.裁剪大小:打开画图--找到矩形选择 形状裁剪完之后,像素会有相应的变化 2.单纯调整像素: 打开画图----重新调整大小(去掉保持纵横比之后可以任意调整大小) 题目:上传 ...
- Doing Homework HDU - 1074 状态压缩
#include<iostream> #include<cstring> #include<cstdio> #include<string> #incl ...
- AcWing 1057. 股票买卖 IV
//f[i,j,1]表示走到第i天已经进行完j次交易并且手中没有股票的所有的购买方式的集合 //f[i,j,0]表示走到第i天并且正在进行第j次交易且手中有货的所有的购买方式的集合 //属性利益最大值 ...