二分图

 

几个二分图性质:

1. 最小点覆盖 等于 最大匹配,

最小点覆盖,实际上就是说选取最少的点,使得图中所有的边都与之相关联。

2. 最大独立集  等于 总点数 - 最小点覆盖。

最大独立集:就是选取一个最大的集合,使得集合的点之间,两两无对应边相连。

3.最小不相交路径覆盖 等于 顶点数 -  最大匹配。

最小边覆盖,在一个DAG中,选取最少的,顶点不相交的路径,覆盖图里所有的点

 

过山车

 HDU - 2063 

模板,分析匈牙利算法,其实就是找得到就匹配,找不到这个点换一下看看能不能匹配;

二分图

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int N=6e2+5;
vector<int>e[N];
int match[N];
bool vis[N];
bool findpath(int u){
    for(int i=0;i<e[u].size();i++){
    int v=e[u][i];
    if(!vis[v]){
    vis[v]=1;
    if(!match[v]||findpath(match[v])){
    match[v]=u;
    return 1;
    }
    }
    }
    return 0;
}   
int main(){
    int k,m,n;
    while(~scanf("%d",&k),k){
    scanf("%d %d",&m,&n);
    for(int i=0;i<=N;i++)match[i]=0,e[i].clear();
    // girl.clear();
    for(int i=1,u,v;i<=k;i++){
    scanf("%d %d",&u,&v);e[u].pb(v);
    // girl.pb(u);
    }
    int ans=0;
    for(int i=1;i<=m;i++){
    memset(vis,0,sizeof vis);
    if(findpath(i))ans++;        
    }
    // cout<<"test"<<endl;
    printf("%dn",ans);

    }
    // system("pause");
    return 0;
}

View Code

 

Asteroids

 POJ - 3041 

题意:n*n的网格,有k个障碍,每次可以把某一行或者某一列删掉,求最小操作次数。

做法;对于给定的图,把每一行,每一列抽象为点,每一个障碍点(x,y),实际上可以抽象为 x 到 y 有一条边。

求最小操作次数,实际上就是求最小点覆盖。

二分图

#include<cstdio>
#include<cstring>
using namespace std;
#define pb push_back
typedef long long ll;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef double db;
const int N=5e2+50;
int gp[N][N];
int match[N],vis[N];
int n,m,k;
void init(){
    memset(match,0,sizeof match);
    // memset(vis,0,sizeof vis);
    memset(gp,0,sizeof gp);

}
bool findpath(int u){
    for(int i=1;i<=n;i++){
        if(gp[u][i]&&!vis[i]){
            vis[i]=1;
            if(!match[i]||findpath(match[i])){
                match[i]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    init();
    scanf("%d %d",&n,&k);
    for(int i=1,u,v;i<=k;i++){
        scanf("%d %d",&u,&v);
        gp[u][v]=1;
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        memset(vis,0,sizeof vis);
        if(findpath(i))ans++;
    }
    // cout<<ans<<endl;
    printf("%dn",ans);
    // system("pause");
    return 0;
}

View Code

 

Air Raid

 POJ - 1422 

题意:一张图,求最小不相交路径覆盖,

二分图

#include<cstdio>
#include<cstring>
// #include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef double db;
const int N=5e2+50;
int gp[N][N];
int match[N],vis[N];
int n,m,k;
void init(){
    memset(match,0,sizeof match);
    // memset(vis,0,sizeof vis);
    memset(gp,0,sizeof gp);

}
bool findpath(int u){
    for(int i=1;i<=n;i++){
        if(gp[u][i]&&!vis[i]){
            vis[i]=1;
            if(!match[i]||findpath(match[i])){
                match[i]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){

     init();
    scanf("%d %d",&n,&k);
    for(int i=1,u,v;i<=k;i++){
        scanf("%d %d",&u,&v);
        gp[u][v]=1;
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        memset(vis,0,sizeof vis);
        if(findpath(i))ans++;
    }
    // cout<<ans<<endl;
    printf("%dn",n-ans);
    }
    // system("pause");
    return 0;
}

View Code

 

Guardian of Decency

 POJ - 2771 

一些男孩和女孩有暧昧关系,选出一个最大集,使得两两之间没有恋爱关系。

 

二分图

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define pb push_back
typedef long long ll;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef double db;
const int N=5e2+50;
int gp[N][N],match[N],vis[N];
int n,m;
void init(){

    memset(gp,0,sizeof gp);

    memset(match,0,sizeof match);

    n=m=0;

}

struct node{

    int h;

    string sex,mus,spo;

}boy[N],girl[N];

bool check(node a,node b){
    if(fabs(a.h-b.h)<=40&&a.sex!=b.sex&&a.mus==b.mus&&a.spo!=b.spo)return 1;
    return 0;
}

bool findpath(int u){
    for(int i=1;i<=m;i++){
        if(gp[u][i]&&!vis[i]){
            vis[i]=1;
            if(!match[i]||findpath(match[i])){
                match[i]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    int t,num;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&num);
        node tmp;
        init();
        for(int i=1;i<=num;i++){
            cin>>tmp.h>>tmp.sex>>tmp.mus>>tmp.spo;
            if(tmp.sex=="M")boy[++n]=tmp;
            else girl[++m]=tmp;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(check(boy[i],girl[j]))gp[i][j]=1;
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++){
            memset(vis,0,sizeof vis);
            if(findpath(i))ans++;
        }
        printf("%dn",num-ans);

    }
    // system("pause");
    return 0;
}

View Code

 

原文链接: https://www.cnblogs.com/littlerita/p/12457992.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    二分图

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/372356

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月3日 上午11:10
下一篇 2023年3月3日 上午11:11

相关推荐