码迷,mamicode.com
首页 > 其他好文 > 详细

二分图小结

时间:2015-09-23 20:54:09      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:

1.hdu1045

题意:给出一张图,图中‘X‘表示wall,‘.‘表示空地,可以放置blockhouse  

同一条直线上只能有一个blockhouse,除非有wall隔开,问在给出的图中  

最多能放置多少个blockhouse  

每个边界与X都可以看成是点,.是边连的是离它最近的上面左面的两个边或者X

技术分享
//二分图匹配(Hopcroft-Carp的算法)。
/*
初始化:g[][]邻接矩阵

调用:res=MaxMatch();  Nx,Ny要初始化!!!

时间复杂大为 O(V^0.5 E)



适用于数据较大的二分匹配

需要queue头文件

********************************************** */
#include<iostream>
#include<string.h>
#include<queue>
#include<stdio.h>
#include<vector>
using namespace std;
const int MAXN=3000;

const int INF=1<<28;

int Mx[MAXN],My[MAXN],Nx,Ny;
vector<int> g[MAXN];
int dx[MAXN],dy[MAXN],dis;

bool vst[MAXN];

bool searchP()

{

    queue<int>Q;
    dis=INF;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(int i=0;i<Nx;i++)

        if(Mx[i]==-1)

        {

            Q.push(i);

            dx[i]=0;

        }

    while(!Q.empty())

    {

        int u=Q.front();

        Q.pop();

        if(dx[u]>dis)  break;

        for(int i = 0; i < g[u].size(); i++){
            int v = g[u][i];
            if(dy[v]==-1)

            {

                dy[v]=dx[u]+1;

                if(My[v]==-1)  dis=dy[v];

                else

                {

                    dx[My[v]]=dy[v]+1;

                    Q.push(My[v]);

                }

            }
        }

    }

    return dis!=INF;

}

bool DFS(int u)

{
    for(int i = 0; i < g[u].size(); i++){
        int v = g[u][i];
        if(!vst[v]&&dy[v]==dx[u]+1)

           {

               vst[v]=1;

               if(My[v]!=-1&&dy[v]==dis) continue;

               if(My[v]==-1||DFS(My[v]))

               {

                   My[v]=u;

                   Mx[u]=v;

                   return 1;

               }

           }
    }
    return 0;

}

int MaxMatch()

{

    int res=0;

    memset(Mx,-1,sizeof(Mx));

    memset(My,-1,sizeof(My));

    while(searchP())

    {

        memset(vst,0,sizeof(vst));

        for(int i=0;i<Nx;i++)

          if(Mx[i]==-1&&DFS(i))  res++;

    }

    return res;

}
const int maxa = 40;
char mp[maxa][maxa];
int num[maxa][maxa];
int main(){
    int n;
    while(scanf("%d", &n), n){
        for(int i = 0; i <= n; i++){
            for(int k = 0; k <= n; k++){
                mp[i][k] = X;
            }
        }
        for(int i = 1; i <= n; i++){
            scanf("%s", mp[i]+1);
        }
        /*for(int i = 0; i <= n; i++){
            printf("%s\n", mp[i]);
        }*/
        int nn = 0;
        for(int i = 0;i <= n; i++){
            for(int k = 0; k <= n; k++){
                if(mp[i][k] == X)
                    num[i][k] = nn++;
            }
        }
        for(int i = 0; i < nn; i++){
            g[i].clear();
        }
        for(int i = 1 ;i <= n; i++){
            for(int k = 1; k <= n; k++){
                int x, y;
                if(mp[i][k] == .){
                    for(int j = k-1; j >= 0; j--){
                        if(mp[i][j] == X){
                            x = num[i][j];
                            break;
                        }
                    }
                    for(int j = i-1; j >= 0; j--){
                        if(mp[j][k] == X){
                            y = num[j][k];
                            break;
                        }
                    }
                    //printf("%d %d\n", x, y);
                    g[x].push_back(y);
                }
            }
        }
        Nx = nn;
        printf("%d\n", MaxMatch());
    }
}
View Code

 

2.hdu3605

题意:有 n 个人选择 m 个星球居住,选择情况和星球居住上限有限制,问是否能全部满足要求。
状态压缩+二分图

技术分享
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define MAXM 555555
#define MAXN 2222
struct Edge{
    int v,cap,next;
}edge[MAXM];

int pre[MAXN];
int cur[MAXN];
int head[MAXN];
int level[MAXN];
int gap[MAXN];
int n,m;
int NV,NE;
void init(){
    NE = 0;
    memset(head, -1, sizeof(head));
}
int SAP(int vs,int vt){
    memset(pre,-1,sizeof(pre));
    memset(level,0,sizeof(level));
    memset(gap,0,sizeof(gap));
    for(int i=0;i<=NV;i++)cur[i]=head[i];
    int u=pre[vs]=vs,maxflow=0,aug=-1;
    gap[0]=NV;
    while(level[vs]<NV){
loop:
        for(int &i=cur[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            if(edge[i].cap&&level[u]==level[v]+1){
                aug==-1?aug=edge[i].cap:(aug=min(aug,edge[i].cap));
                pre[v]=u;
                u=v;
                if(v==vt){
                    maxflow+=aug;
                    for(u=pre[u];v!=vs;v=u,u=pre[u]){
                        edge[cur[u]].cap-=aug;
                        edge[cur[u]^1].cap+=aug;
                    }
                    aug=-1;
                }
                goto loop;
            }
        }
        int minlevel=NV;
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            if(edge[i].cap&&minlevel>level[v]){
                cur[u]=i;
                minlevel=level[v];
            }
        }
        gap[level[u]]--;
        if(gap[level[u]]==0)break;
        level[u]=minlevel+1;
        gap[level[u]]++;
        u=pre[u];
    }
    return maxflow;
}

void addedge(int u,int v,int cap,int cc=0){

    //printf("*%d %d %d\n", u, v, cap);
    edge[NE].cap=cap;edge[NE].v=v;
    edge[NE].next=head[u];head[u]=NE++;

    edge[NE].cap=cc;edge[NE].v=u;
    edge[NE].next=head[v];head[v]=NE++;
}

int num[(1<<11) + 100];
int main(){
    int n, m;
    while(scanf("%d%d", &n, &m)!=EOF){          //将所有的点压缩到1~(1<<m) - 1  num 表示这样的人有多少
        init();
        memset(num, 0, sizeof(num));
        for(int i =0;i < n; i++){
            int id = 0;
            for(int k = 0; k < m; k++){
                int x;
                scanf("%d", &x);
                if(x){
                    id += 1<<k;
                }
            }
            num[id] ++;
        }
        for(int i = 0;i < m; i++){
            int x;
            scanf("%d", &x);
            num[(1<<m) + i] = x;                //星球的点变成(1<<m) + i num表示每个星球能够承载的人数
        }
        int src = (1<<m) +m + 1;
        int sink = (1<<m) + m +2;
        NV = sink+1;
        for(int i = 0;i < (1<<m); i++){
            addedge(src, i, num[i]);                //从起点到每种人建立一条人数的边
            for(int k = 0; k < m;k ++){
                if((1<<k) & i){
                    addedge(i,(1<<m) + k, num[i]);          //每种人到对应的每个星球都建立一条人数的边
                }
            }
        }
        for(int i =0 ;i < m; i++){
            addedge(i+(1<<m), sink, num[i+(1<<m)]);     //星球到终点建立一条星球能承载最大人数的边
        }
        //printf("%d\n", SAP(src, sink));
        if(SAP(src, sink) == n) printf("YES\n");
        else printf("NO\n");
    }
}
View Code

 

3.hdu 5093

技术分享
//二分图匹配(Hopcroft-Carp的算法)。
/*
初始化:g[][]邻接矩阵

调用:res=MaxMatch();  Nx,Ny要初始化!!!

时间复杂大为 O(V^0.5 E)



适用于数据较大的二分匹配

需要queue头文件

********************************************** */
#include<iostream>
#include<string.h>
#include<queue>
#include<stdio.h>
#include<vector>
using namespace std;
const int MAXN=3000;

const int INF=1<<28;

int Mx[MAXN],My[MAXN],Nx,Ny;
vector<int> g[MAXN];
int dx[MAXN],dy[MAXN],dis;

bool vst[MAXN];

bool searchP()

{

    queue<int>Q;
    dis=INF;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(int i=0;i<Nx;i++)

        if(Mx[i]==-1)

        {

            Q.push(i);

            dx[i]=0;

        }

    while(!Q.empty())

    {

        int u=Q.front();

        Q.pop();

        if(dx[u]>dis)  break;

        for(int i = 0; i < g[u].size(); i++){
            int v = g[u][i];
            if(dy[v]==-1)

            {

                dy[v]=dx[u]+1;

                if(My[v]==-1)  dis=dy[v];

                else

                {

                    dx[My[v]]=dy[v]+1;

                    Q.push(My[v]);

                }

            }
        }

    }

    return dis!=INF;

}

bool DFS(int u)

{
    for(int i = 0; i < g[u].size(); i++){
        int v = g[u][i];
        if(!vst[v]&&dy[v]==dx[u]+1)

           {

               vst[v]=1;

               if(My[v]!=-1&&dy[v]==dis) continue;

               if(My[v]==-1||DFS(My[v]))

               {

                   My[v]=u;

                   Mx[u]=v;

                   return 1;

               }

           }
    }
    return 0;

}

int MaxMatch()

{

    int res=0;

    memset(Mx,-1,sizeof(Mx));

    memset(My,-1,sizeof(My));

    while(searchP())

    {

        memset(vst,0,sizeof(vst));

        for(int i=0;i<Nx;i++)

          if(Mx[i]==-1&&DFS(i))  res++;

    }

    return res;

}
const int maxa = 400;
char mp[maxa][maxa];
int num[maxa][maxa];
int main(){
    int n, m;
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%d%d", &n, &m);
        for(int i = 0; i <= n; i++){
            for(int k = 0; k <= m; k++){
                mp[i][k] = #;
            }
        }
        for(int i = 1; i <= n; i++){
            scanf("%s", mp[i]+1);
        }
        /*for(int i = 0; i <= n; i++){
            printf("%s\n", mp[i]);
        }*/
        int nn = 0;
        for(int i = 0;i <= n; i++){
            for(int k = 0; k <= m; k++){
                if(mp[i][k] == #)
                    num[i][k] = nn++;
            }
        }
        for(int i = 0; i < nn; i++){
            g[i].clear();
        }
        for(int i = 1 ;i <= n; i++){
            for(int k = 1; k <= m; k++){
                int x, y;
                if(mp[i][k] == *){
                    for(int j = k-1; j >= 0; j--){
                        if(mp[i][j] == #){
                            x = num[i][j];
                            break;
                        }
                    }
                    for(int j = i-1; j >= 0; j--){
                        if(mp[j][k] == #){
                            y = num[j][k];
                            break;
                        }
                    }
                    //printf("%d %d\n", x, y);
                    g[x].push_back(y);
                }
            }
        }
        Nx = nn;
        printf("%d\n", MaxMatch());
    }
}
View Code

 

二分图小结

标签:

原文地址:http://www.cnblogs.com/icodefive/p/4833230.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!