• 二分图小结


    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
    ", 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
    ", x, y);
                        g[x].push_back(y);
                    }
                }
            }
            Nx = nn;
            printf("%d
    ", 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
    ", 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
    ", SAP(src, sink));
            if(SAP(src, sink) == n) printf("YES
    ");
            else printf("NO
    ");
        }
    }
    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
    ", 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
    ", x, y);
                        g[x].push_back(y);
                    }
                }
            }
            Nx = nn;
            printf("%d
    ", MaxMatch());
        }
    }
    View Code

    4.HDU 1281

    //二分图匹配(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=111;
    
    const int INF=1<<28;
    
    int Mx[MAXN],My[MAXN],Nx,Ny;
    int g[MAXN][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 v =0 ; v < Ny; v++){
                if(g[u][v] && 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 v = 0; v < Ny; v++){
            if(g[u][v] && !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 = 105 * 111;
    int x[maxa], y[maxa];
    int main(){
        int n, m, q;
        int cas = 1;
        while(scanf("%d%d%d", &n, &m, &q)!=EOF){
            memset(g, 0, sizeof(g));
            for(int i =0 ;i < q; i++){
                scanf("%d%d", &x[i], &y[i]);
                g[x[i]][y[i]] = 1;
            }
            Nx = n+1;
            Ny = m+1;
            int sum = MaxMatch();
            int ans = 0;
            for(int i =0 ;i < q; i++){
                g[x[i]][y[i]] = 0;
                if(MaxMatch() < sum) ans ++;
                g[x[i]][y[i]] = 1;
            }
            printf("Board %d have %d important blanks for %d chessmen.
    ", cas++, ans, sum);
        }
    }
    View Code

    5.HDU 2063

    //二分图匹配(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;
    
    }
    int main(){
        int q, m, n;
        while(scanf("%d", &q)!=EOF){
            if(q == 0) return 0;
            scanf("%d%d", &m, &n);
    
            for(int i = 1; i <= m; i++){
                g[i].clear();
            }
            while(q--){
                int x, y;
                scanf("%d%d", &x, &y);
                g[x].push_back(y);
            }
            Nx = m+1;
            printf("%d
    ", MaxMatch());
        }
    }
    View Code

    6.POJ 3020

    //二分图匹配(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 =111;
    char mp[maxa][maxa];
    int num[maxa][maxa];
    int move[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
    int main(){
        int t, n, m;
        scanf("%d", &t);
        while(t--){
            scanf("%d%d", &n, &m);
            for(int i = 0;i < n; i++){
                scanf("%s", mp[i]);
            }
            int sum = 0;
            for(int i = 0; i < n; i++){
                for(int k = 0;k < m; k++){
                    if(mp[i][k] == '*'){
                        sum ++;
                    }
                }
            }
            Nx = 0;
            for(int i =0 ;i < n; i++){
                for(int k =0 ;k < m; k++){
                    num[i][k] = Nx ++;
                }
            }
            for(int i =0;i < Nx; i++){
                g[i].clear();
            }
            for(int i = 0;i < n; i++){
                for(int k = 0; k < m; k++){
                    if((i+k) %2 == 1 && mp[i][k] == '*'){
                        for(int j = 0; j < 4;j++){
                            int x = i+ move[j][0], y = k + move[j][1];
                            if(0 <= x && x < n && 0 <= y && y < m && mp[x][y] == '*'){
                                g[num[i][k]].push_back(num[x][y]);
                            }
                        }
                    }
                }
            }
            //printf("%d
    ", sum);
            printf("%d
    ", sum -MaxMatch());
        }
    }
    View Code

    7.POJ 2446

    //二分图匹配(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 =111;
    char mp[maxa][maxa];
    int num[maxa][maxa];
    int MOVE[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
    int main(){
        int n, m, q;
        while(scanf("%d%d%d", &n, &m , &q)!=EOF){
    
            int sum ;
            for(int i =0 ;i < n; i++){
                for(int k =0 ;k < m;k ++){
                    mp[i][k] = '*';
                }
            }
            while(q--){
                int x, y;
                scanf("%d%d", &y, &x);
                x--, y--;
                mp[x][y] = '&';
            }
            Nx = 0;
            for(int i =0 ;i < n; i++){
                for(int k =0 ;k < m; k++){
                    num[i][k] = Nx ++;
                }
            }
            for(int i =0;i < Nx; i++){
                g[i].clear();
            }
            for(int i = 0;i < n; i++){
                for(int k = 0; k < m; k++){
                    if((i+k) %2 == 1 && mp[i][k] == '*'){
                        for(int j = 0; j < 4;j++){
                            int x = i+ MOVE[j][0], y = k + MOVE[j][1];
                            if(0 <= x && x < n && 0 <= y && y < m && mp[x][y] == '*'){
                                g[num[i][k]].push_back(num[x][y]);
                            }
                        }
                    }
                }
            }
            sum = 0;
            for(int i =0 ;i < n; i++){
                for(int k= 0; k < m; k++){
                    if(mp[i][k] == '*') sum ++;
                }
            }
            if(sum == MaxMatch() * 2){
                printf("YES
    ");
            }else{
                printf("NO
    ");
            }
        }
    }
    View Code

    今天水了十多道图论题,脑袋好疼,虽然代码行数加起来也有一两千,但是都是水题,练了一天手速.....有了女朋友也不能放弃治疗啊..........

    8.POJ 2724

    题意:m个长度为n的2进制数,可能某一位是*代替(代表*=1和*=0都被包含了)。要求用最少的另外一些二进制数(也可以某一位被*代替)将原来的那些覆盖(且只能覆盖一次),且要求不能覆盖原本不存在的二进制数。

    刚开始想直接对每个点连接连接大于这个点编号并且能够相连的,我以为这样就能保证连线不重复,但是,如果有1-2,2-3这样的连线的话2相当于被使用了两次,我犯的错误就是没有将点分成两部分。对二分图的理解有加深的一层,虽然是好久前就应该掌握的,希望亚洲区之前能过把图论弄得差不多。

    这段时间有点浮躁焦虑,不想太多了,抱着失败的觉悟和奔向成功的目标再努力一次吧......

    //二分图匹配(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>
    #include<map>
    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;
    
    }
    map<int, int> mp;
    const int maxa = 2222;
    char str[maxa][11];
    char chess[maxa][11];
    int main(){
        int n, m;
        while(scanf("%d%d", &n, &m), n+m){
            mp.clear();
            int num_chess = 0;
            for(int i = 0;i < m; i++){
                scanf("%s", str[i]);
                int star = 0;
                for(int k =0;k < n; k++){
                    if(str[i][k] == '*'){
                        star = 1;
                        str[i][k] = '0';
                        int aa = 0;
                        for(int j =0; j < n; j++){
                            chess[num_chess][j] = str[i][j];
                            aa = aa*2 + str[i][j] - '0';
                        }//num_chess++;
    
                        if(mp[aa] == 0){
                            mp[aa] = 1;
                            num_chess++;
                        }
    
                        str[i][k] = '1';
                        aa = 0;
                        for(int j =0; j < n; j++){
                            chess[num_chess][j] = str[i][j];
                            aa = aa*2 + str[i][j] - '0';
                        }//num_chess++;
    
                        if(mp[aa] == 0){
                            mp[aa] = 1;
                            num_chess++;
                        }
                        break;
                    }
                }
                if(!star){
                    int aa = 0;
                    for(int j =0; j < n; j++){
                        chess[num_chess][j] = str[i][j];
                        aa = aa*2 + str[i][j] - '0';
                    }//num_chess++;
    
                    if(mp[aa] == 0){
                        mp[aa] = 1;
                        num_chess++;
                    }
                }
            }
            for(int i = 0 ; i < num_chess; i++){
                g[i].clear();
            }
            /*for(int i =0; i < num_chess; i++){
                printf("%s
    ", chess[i]);
            }*/
            for(int i = 0;i < num_chess; i++){
                for(int k = 0; k < num_chess; k++){
                    int sum_def = 0;
                    int ss =0;
                    for(int j = 0; j < n; j++){
                        if(chess[i][j] == '1') ss++;
                        if(chess[i][j] != chess[k][j])
                        sum_def ++;
                    }
                    if(ss %2 ==1 && sum_def == 1){
                        g[i].push_back(k);
                    }
                }
            }
            Nx = num_chess;
            printf("%d
    ", num_chess -MaxMatch());
        }
    }
    View Code

        

    9.POJ 3692

    题意:已知班级有g个女孩和b个男孩,所有女生之间都相互认识,所有男生之间也相互认识,给出m对关系表示哪个女孩与哪个男孩认识。现在要选择一些学生来组成一个团,使得里面所有人都认识,求此团最大人数。

    这个题只要将没有关系的两个人连线,求最大点独立集就好,最大点独立集的求法是总点数减去最大匹配数

    //二分图匹配(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 = 222;
    int G[maxa][maxa];
    int main(){
        int n, m, q;
        int cas = 1;
        while(scanf("%d%d%d", &n, &m, &q)!=EOF){
            if(n == 0 && m == 0 && q == 0) return 0;
    
            for(int i = 1; i <= n; i++){
                for(int k = 1; k <= m; k++){
                    G[i][k] = 1;
                }
            }
            while(q--){
                int u, v;
                scanf("%d%d", &u, &v);
                G[u][v] = 0;
            }
            for(int i = 1;i <= n; i++){
                g[i].clear();
                for(int k = 1;k  <= m; k++){
                    if(G[i][k]){
                        g[i].push_back(k);
                    }
                }
            }
            Nx = n+1;
            printf("Case %d: %d
    ",cas++,  n+m - MaxMatch());
        }
    }
    View Code
  • 相关阅读:
    ABP-AsyncLocal的使用
    ABP-多个DbContext实现事物更新
    ABP取其精华
    VS2019和net core 3.0(整理不全,但是孰能生巧)
    consul部署多台Docker集群
    Arcgis runtime sdk .net 二次开发
    C# 依赖注入 & MEF
    自动构建环境搭建
    C# 调用C/C++动态链接库,结构体中的char*类型
    C# 调用C++DLL 类型转换
  • 原文地址:https://www.cnblogs.com/icodefive/p/4833230.html
Copyright © 2020-2023  润新知