二分图

 

几个二分图性质:

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("%d\n",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("%d\n",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("%d\n",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("%d\n",num-ans);

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

 

posted @ 2020-03-10 19:17  无声-黑白  阅读(228)  评论(0)    收藏  举报