原题链接

此题求二分图的最小点覆盖,数值上等于该二分图的最大匹配。得知此结论可以将图染色,建有向图,然后跑匈牙利/网络流,如下。然而...

#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)的更多相关文章

  1. HihoCoder1127 二分图三·二分图最小点覆盖和最大独立集

    二分图三·二分图最小点覆盖和最大独立集 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上次安排完相亲之后又过了挺长时间,大家好像都差不多见过面了.不过相亲这个事不是说 ...

  2. hihoCoder #1127 : 二分图二·二分图最小点覆盖和最大独立集

    #1127 : 二分图二·二分图最小点覆盖和最大独立集 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 在上次安排完相亲 ...

  3. Asteroids POJ - 3041 二分图最小点覆盖

       Asteroids POJ - 3041 Bessie wants to navigate her spaceship through a dangerous asteroid field in ...

  4. POJ2226 Muddy Fields(二分图最小点覆盖集)

    题目给张R×C的地图,地图上*表示泥地..表示草地,问最少要几块宽1长任意木板才能盖住所有泥地,木板可以重合但不能盖住草地. 把所有行和列连续的泥地(可以放一块木板铺满的)看作点且行和列连续泥地分别作 ...

  5. POJ1325 Machine Schedule(二分图最小点覆盖集)

    最小点覆盖集就是在一个有向图中选出最少的点集,使其覆盖所有的边. 二分图最小点覆盖集=二分图最大匹配(二分图最大边独立集) 这题A机器的n种模式作为X部的点,B机器的m种模式作为Y部的点: 每个任务就 ...

  6. hihoCoder #1127:二分图最小点覆盖和最大独立集

    题目大意:求二分图最小点覆盖和最大独立集. 题目分析:如果选中一个点,那么与这个点相连的所有边都被覆盖,使所有边都被覆盖的最小点集称为最小点覆盖,它等于最大匹配:任意两个点之间都没有边相连的最大点集称 ...

  7. [POJ] 2226 Muddy Fields(二分图最小点覆盖)

    题目地址:http://poj.org/problem?id=2226 二分图的题目关键在于建图.因为“*”的地方只有两种木板覆盖方式:水平或竖直,所以运用这种方式进行二分.首先按行排列,算出每个&q ...

  8. 二分图 最小点覆盖 poj 3041

    题目链接:Asteroids - POJ 3041 - Virtual Judge  https://vjudge.net/problem/POJ-3041 第一行输入一个n和一个m表示在n*n的网格 ...

  9. 四川第七届 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), ...

随机推荐

  1. t-SNE and PCA

    1.t-SNE 知乎 t-分布领域嵌入算法 虽然主打非线性高维数据降维,但是很少用,因为 比较适合应用于可视化,测试模型的效果 保证在低维上数据的分布与原始特征空间分布的相似性高 因此用来查看分类器的 ...

  2. PAT (Basic Level) Practice (中文)1041 考试座位号 (15 分)

    每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位.正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考 ...

  3. c语言中 char* 和 unsigned char* 的区别浅析(转)

    原文:https://blog.csdn.net/guotianqing/article/details/77341657 背景最近在项目中遇到了一个编译警告,是因为定义的变量为char[],而在使用 ...

  4. 禁止PotPlayer自动添加同一目录内连续文件

    问题描述 默认情况下PotPlayer会自动向播放列表添加相似文件 统一目录下大量连续文件会被同时加载 解决办法 参数选项-基本-基本设置-相似文件策略 设置为仅打开选定的文件

  5. mybatis第一天02

    mybatis第二天02 1.映射文件之输入输出映射 1.1映射文件之输入映射类型(parameterType) 1.1.1简单类型 当parameterType为简单类型时,我们只需要直接填写“in ...

  6. Codeforce 25A - IQ test (唯一奇偶)

    Bob is preparing to pass IQ test. The most frequent task in this test is to find out which one of th ...

  7. Mapped Statements collection does not contain value for xxx

    这是我第二次遇到的这个问题了,总结下. 第一次的问题是 mybatis的sqlSessionFactory的mapperLocations,配置的是这个路径下的所有映射文件,但是我没写的没有在该路径下 ...

  8. 创建登录WEB UI页面的Business role.

    1: Define business role 2:  business role 中可以指定 config key,  该config key可以用于UI configurationo determ ...

  9. [P5490] 【模板】扫描线 - 线段树

    求 \(n\) 个矩形的面积并 Solution 将矩形转化为 \(y_1\) 位置的 + 修改 和 \(y_2\) 位置的 - 修改.然后按照 \(+y\) 顺序依次处理所有的修改,到达的一个新的位 ...

  10. R parallel包实现多线程1

    并行执行 Yes! Well done! Socket clusters are initialized without variables, so a_global_var wasn't found ...