一,最少顶点覆盖:

     求最少多少个顶点能够覆盖二分图中的所有的边,最小顶点覆盖=最大匹配=>对于二分图,求出最大匹配后只可能有两种边,未匹配边和匹配边,那么如果未匹配边未被任何一个顶点覆盖,那么这条边完全可以加入最大匹配中,所以最大匹配必然能够覆盖所有的边,得证。

poj1325:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
int read(){
    int x=0;
    char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)){
        x=x*10+c-'0';
        c=getchar();
    }
    return x;
}
int v[105],f[105],h[105],n,m,k;
struct edge{
    int to,next;
};
edge e[1005];
int dfs(int x){
    for(int j=h[x];j;j=e[j].next){
        int tmp=e[j].to;
        if(v[tmp]) continue;
        v[tmp]=1;
        if(f[tmp]<0||dfs(f[tmp])){
            f[tmp]=x;
            return 1;
        }
    }
    return 0;
}
int main(){
    while(n=read()){
        m=read();k=read();
        int cur=0;
        clr(f,-1);clr(h,0);
        rep(i,k){
            int u=read(),o=read(),ee=read();
            e[++cur].to=ee;
            e[cur].next=h[o];
            h[o]=cur;
        }
        int ans=0;
        rep(i,n){
            clr(v,0);
            if(dfs(i))
              ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}

二,最大独立集。其实就是求有多少个点之间可以互相到达,因为可以求不能够互相到达的边的最小覆盖点,然后用所有的点数减去最小覆盖点就好了,不难理解;套模板套的好兴奋2333

poj3692:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
const int nmax=205;
int f[nmax][nmax],v[nmax],l[nmax];
int n,m,k;
int read(){
    int x=0;
    char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)){
        x=x*10+c-'0';
        c=getchar();
    }
    return x;
}
bool dfs(int u){
    rep(i,m){
        if(!f[u][i]){
            int tmp=i;
            if(!v[tmp]){
                v[tmp]=1;
                if(l[tmp]<0||dfs(l[tmp])){
                    l[tmp]=u;
                    return true;
                }
            }
        }
    }
    return false;
}
int main(){
    int cur=0;
    while((n=read())&&(m=read())&&(k=read())){
        clr(f,0);
        rep(i,k){
            int u=read(),o=read();
            f[u][o]=1;
        }
        clr(l,-1);
        int ans=0;
        rep(i,n){
            clr(v,0);
            if(dfs(i))
              ans++;
        }
        printf("Case %d: %d\n",++cur,n+m-ans);
    }
    return 0;
}

再水一题。。。

poj2239:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
struct edge{
    int to,next;
};
edge e[30005];
int f[200],v[200],h[305],n,m,k;
int read(){
    int x=0;
    char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)){
        x=x*10+c-'0';
        c=getchar();
    }
    return x;
}
bool dfs(int u){
    for(int i=h[u];i;i=e[i].next){
        int tmp=e[i].to;
        if(!v[tmp]){
            v[tmp]=1;
            if(f[tmp]<0||dfs(f[tmp])){
                f[tmp]=u;
                return true;
            }
        }
    }
    return false;
}
int main(){
    while(scanf("%d",&n)==1){
        int cur=0;
        clr(f,-1);clr(h,0);
        rep(j,n){
            int tmp=read();
            rep(i,tmp){
                int u=read(),o=read();
                o=(u-1)*12+o;
                e[++cur].to=o;
                e[cur].next=h[j];
                h[j]=cur;
            }
        }
        int ans=0;
        rep(i,n){
            clr(v,0);
            if(dfs(i))
              ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}