您的位置:首页 > 其它

二分图相关问题

2016-04-06 20:27 323 查看

 1。一个二分图中的最大匹配数等于这个图中的最小点覆盖数

König定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数。最小点覆盖:假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖所有的边。

 2。最小路径覆盖=最小路径覆盖=|G|-最大匹配数

 在一个N*N的有向图中,路径覆盖就是在图中找一些路经,使之覆盖了图中的所有顶点,
 且任何一个顶点有且只有一条路径与之关联;(如果把这些路径中的每条路径从它的起始点走到它的终点,
 那么恰好可以经过图中的每个顶点一次且仅一次);如果不考虑图中存在回路,那么每条路径就是一个弱连通子集.

由上面可以得出:

 1.一个单独的顶点是一条路径;
 2.如果存在一路径p1,p2,......pk,其中p1 为起点,pk为终点,那么在覆盖图中,顶点p1,p2,......pk不再与其它的
   顶点之间存在有向边.

最小路径覆盖就是找出最小的路径条数,使之成为G的一个路径覆盖.

 路径覆盖与二分图匹配的关系:最小路径覆盖=|G|-最大匹配数;

 

3。二分图最大独立集=顶点数-二分图最大匹配

独立集:图中任意两个顶点都不相连的顶点集合。

 

【bzoj1562】 变换序列

大概想了一下构图,果然还只是停留在09年noi的层面。。。

看了一下hzwer安利的题解,好多种解法,看了解法三和解法四(懒),发现字典序最小还是很实现的。

方法是:每次倒序找增广路,优先找序号小的点,这样就可以保证越前面的点越优,当然跟这道题的特殊构图方法也有一定联系。

一个很奇怪的地方是,题解的std明明跑了n遍的memset,怎么看都是n^2,时间只要80ms,不服。。。

可能我还有哪里没优化的地方,在这里MARK一下。

#include<cstdio>
#include<algorithm>
#define N 3010
using namespace std;
int edgenum,ans,A,B,T1,T2,m;
int match
,ban
,flag
,head
,mtime
,vet[9000010],next[9000010],map[3010][3010];
int a
,b
;
void add(int u,int v){
edgenum++;vet[edgenum]=v;next[edgenum]=head[u];head[u]=edgenum;
}
int count(int x){
int re=0;
while(x){
x-=x&(-x);//依次削去x最末尾的1
re++;
}return re;
}
int dfs(int u){
int e=head[u];
if(ban[u]==T1)return 0;
while(e>0){
int v=vet[e];
if(ban[v]!=T1&&flag[v]!=T2){
flag[v]=T2;
if(mtime[v]!=T1||dfs(match[v])){
match[v]=u;mtime[v]=T1;
return 1;
}
}
e=next[e];
}return 0;
}
int inde(int x=0,int y=0){
int re=0;T1++;
for(int i=1;i<=B;i++)
if((map[x][i]==0)||(map[y][i]==0))ban[i]=T1,re++;
for(int i=1;i<=B;i++)
if(b[i]&1)//从奇数开始找
{
T2++; if(dfs(i)==1)re++;
}return re;
}
int main()
{
scanf("%d%d%d",&A,&B,&m);ans=1;int ja=0,oa=0;
for(int i=1;i<=A;i++){
scanf("%d",&a[i]);
if(a[i]%2==1)ja++;else oa++;
}if(ja>0)if(oa>0)ans=2;
for(int i=1;i<=B;i++)scanf("%d",&b[i]);
for(int i=1;i<=m;i++){
int x,y;scanf("%d%d",&x,&y);
map[x][y]=1;//反图中 map==1的ban掉
}
for(int i=1;i<=B;i++)map[0][i]=1;
for(int i=1;i<=B;i++)if(b[i]&1)//是奇数
for(int j=1;j<=B;j++)if((b[j]&1)==0)//是偶数
if(count(b[i]|b[j])%2==0)add(i,j);
ans=max(ans,B-inde()); //寻找B图内最大独立集
for(int i=1;i<=A;i++)
ans=max(ans,B-inde(i)+1);
for(int i=1;i<=A;i++)if(a[i]%2==1)
for(int j=1;j<=A;j++)if(a[j]%2==0){
ans=max(ans,B-inde(i,j)+2);
}
printf("%d\n",ans);return 0;
}
bzoj2744

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: