zoukankan      html  css  js  c++  java
  • 一些二分匹配的题

    /*poj1469简单的二分匹配*/
    
    #include<stdio.h>
    #include<string.h>
    int map[1005][1005],vis[2000],match[2000];
    int n,m;
    int dfs(int u)
    {
        int i,j;
        for(i=1;i<=n;i++)//根据课
        {
            if(!vis[i]&&map[u][i])
            {
                vis[i]=1;
                if(match[i]==-1||dfs(match[i]))
                {
                    match[i]=u;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
        int i,j,t;
        scanf("%d",&t);
        while(t--)
        {
            memset(map,0,sizeof(map));
            scanf("%d%d",&m,&n);//m人 n课
            for(i=1;i<=m;i++)
            {
                int l,x;
                scanf("%d",&l);
                while(l--)
                {
                    scanf("%d",&x);
                    map[i][x]=1;
                }
            }
            int ans=0;
            memset(match,-1,sizeof(match));
            for(i=1;i<=m;i++)
            {
                memset(vis,0,sizeof(vis));
                if(dfs(i))
                    ans++;
            }
            if(ans==m)
                printf("YES
    ");
            else printf("NO
    ");
        }
    }
    
    




    /**poj2446*/ /*第一次交数组开小了 ,改好就A了,哈哈,开心*/ #include<stdio.h> #include<string.h> int map[50][50],g[1205][1205],n,m,k,sum,vis[3000],match[3000]; void makemap() { memset(g,0,sizeof(g)); int i,j; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(map[i][j]&&(i+1)<=n) g[map[i][j]][map[i+1][j]]=1;//下面的 if(map[i][j]&&(i-1)>=1) g[map[i][j]][map[i-1][j]]=1;//上面的 if(map[i][j]&&(j+1)<=m) g[map[i][j]][map[i][j+1]]=1;//右面的 if(map[i][j]&&(j-1)>=1) g[map[i][j]][map[i][j-1]]=1;//左面的 } } } int dfs(int u) { int i,j; for(i=1;i<sum;i++) { if(g[u][i]&&!vis[i]) { vis[i]=1; if(match[i]==-1||dfs(match[i])) { match[i]=u; return 1; } } } return 0; } int main() { int i,j; while(scanf("%d%d%d",&n,&m,&k)!=EOF) { sum=1; for(i=1;i<=n;i++) for(j=1;j<=m;j++) map[i][j]=sum++; for(i=1;i<=k;i++) { int x,y; scanf("%d%d",&x,&y); map[y][x]=0; } makemap(); int ans=0; memset(match,-1,sizeof(match)); for(i=1;i<sum;i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) { ans++; } } if(ans+k==(n*m)) printf("YES "); else printf("NO "); } }
    //最大独立集
    //hdu1068
    #include<stdio.h>
    #include<string.h>
    struct node
    {
        int x;
        int next;
    }edge[2000];
    int head[2000],n,vis[2000],match[2000];
    int index;
    void add(int xx,int yy)
    {
        edge[index].x=yy;
        edge[index].next=head[xx];
        head[xx]=index++;
    }
    int dfs(int u)
    {
        int i,j;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            int tmp=edge[i].x;
            if(!vis[tmp])
            {
                vis[tmp]=1;
                if(match[tmp]==-1||dfs(match[tmp]))
                {
                    match[tmp]=u;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
        int i,j,t;
        while(scanf("%d",&n)!=EOF)
        {
            memset(head,-1,sizeof(head));
            memset(match,-1,sizeof(match));
            index=0;
            for(i=0;i<n;i++)
            {
                scanf("%d: (%d)",&j,&t);
                while(t--)
                {
                    int l;
                    scanf("%d",&l);
                    add(j,l);
                }
            }
            int ans=0;
            for(i=0;i<n;i++)
            {
                memset(vis,0,sizeof(vis));
                if(dfs(i))
                    ans++;
            }
            if(ans%2)ans+=1;
            printf("%d
    ",n-ans/2);//最大独立集=顶点总数-二分图最大匹配
        }
    }
    
    
    
    
    
    /*
    最小顶点覆盖 == 最大匹配(双向图)/2;
    hdu1054 要双向图
    */ #include<stdio.h> #include<string.h> struct node { int v; int next; }edge[20000]; int vis[2000],head[2000],match[2000]; int n,m,index; void add(int x,int y) { edge[index].v=y; edge[index].next=head[x]; head[x]=index++; } int dfs(int u) { int i,j; for(i=head[u];i!=-1;i=edge[i].next) { int tmp=edge[i].v; if(!vis[tmp]) { vis[tmp]=1; if(match[tmp]==-1||dfs(match[tmp])) { match[tmp]=u; return 1; } } } return 0; } int main() { int i,j,t; while(scanf("%d",&n)!=EOF) { index=1; memset(head,-1,sizeof(head)); memset(match,-1,sizeof(match)); for(i=0;i<n;i++) { int l; scanf("%d:(%d)",&l,&t); while(t--) { int x; scanf("%d",&x); add(l,x); add(x,l); } } int ans=0; for(i=0;i<n;i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) { ans++; } } printf("%d ",ans/2); } }
    hdu2119
    建图发现同一行和同一列能够消除; 然后可以发现就是从这一点出发,同一行,同一列有1的点就能够连接起来; 然后就是一张2分图;
    0 0 0 1 0 1 0 1 0 二分图 :2->1,2->3,3->2; /**hdu2119**/ //建图的重要性,把行和列作为图来写 #include<stdio.h> #include<string.h> int map[200][200]; int n,m; int vis[10005],match[10005],index; int dfs(int u) { int i,j; for(i=1;i<=m;i++) { if(!vis[i]&&map[u][i]==1) { vis[i]=1; if(match[i]==-1||dfs(match[i])) { match[i]=u; return 1; } } } return 0; } int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0)break; memset(match,-1,sizeof(match)); memset(map,0,sizeof(map)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) { scanf("%d",&map[i][j]); } int ans=0; for(i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } printf("%d ",ans); } }
     1 //hdu5090 二分匹配
     2 #include<stdio.h>
     3 #include<string.h>
     4 int match[103],vis[103];
     5 int map[103][103];
     6 int n,k;
     7 int dfs(int u)
     8 {
     9     int i,j;
    10     for(i=1;i<=n;i++)
    11     {
    12         if(!vis[i]&&map[u][i])
    13         {
    14             vis[i]=1;
    15             if(match[i]==-1||dfs(match[i]))
    16             {
    17                 match[i]=u;
    18                 return 1;
    19             }
    20         }
    21     }
    22     return 0;
    23 }
    24 int main()
    25 {
    26     int i,j;
    27     int t;
    28     scanf("%d",&t);
    29     while(t--)
    30     {
    31         memset(match,-1,sizeof(match));
    32         memset(map,0,sizeof(map));
    33         scanf("%d%d",&n,&k);
    34         for(i=1;i<=n;i++)
    35         {
    36             int x;
    37             scanf("%d",&x);
    38             int t=x;
    39             while(t<=n)
    40             {
    41                 map[t][i]=1;
    42                 t+=k;
    43             }
    44         }
    45         int ans=0;
    46         for(i=1;i<=n;i++)
    47         {
    48             memset(vis,0,sizeof(vis));
    49             if(dfs(i))
    50                 ans++;
    51         }
    52         if(ans==n)
    53             printf("Jerry
    ");
    54         else printf("Tom
    ");
    55     }
    56 }

     最感人的二分匹配题 不会建图。。

     zoj  Place the Robots

      1 #include<stdio.h>
      2 #include<string.h>
      3 char map[52][52];
      4 int g[2600][2600],n,m,match[2600];
      5 int x[52][52],y[52][52];
      6 int xx,yy;
      7 bool vis[2600];
      8 bool dfs(int u)
      9 {
     10     int i,j;
     11     for(i=1;i<=yy;i++)
     12     {
     13         if(!vis[i]&&g[u][i])
     14         {
     15             vis[i]=true;
     16             if(match[i]==-1||dfs(match[i]))
     17             {
     18                 match[i]=u;
     19                 return true;
     20             }
     21         }
     22     }
     23     return false;
     24 }
     25 int main()
     26 {
     27     int i,j,ff,t,flag;
     28     scanf("%d",&t);
     29     ff=0;
     30     while(t--)
     31     {
     32         scanf("%d%d",&n,&m);
     33         for(i=0;i<n;i++)
     34             scanf("%s",map[i]);
     35         memset(g,0,sizeof(g));
     36         int num=0;
     37         flag=0;
     38         memset(x,0,sizeof(x));
     39         memset(y,0,sizeof(y));
     40         for(i=0;i<n;i++)//按行来
     41         {
     42             flag=0;
     43             for(j=0;j<m;j++)
     44             {
     45                 if(map[i][j]=='o')
     46                 {
     47                     if(!flag)
     48                         num++;
     49                     x[i][j]=num;flag=1;
     50                 }
     51                 else if(map[i][j]=='#')
     52                 {
     53                     flag=0;
     54                 }
     55             }
     56         }
     57         xx=num;num=0;
     58         //竖直方向
     59         for(i=0;i<m;i++)
     60         {
     61             flag=0;
     62             for(j=0;j<n;j++)
     63             {
     64                 if(map[j][i]=='o')
     65                 {
     66                     if(!flag)
     67                         num++;
     68                     y[j][i]=num;
     69                     flag=1;
     70                 }
     71                 else if(map[j][i]=='#')
     72                     flag=0;
     73             }
     74         }
     75         yy=num;
     76         //建新图
     77         for(i=0;i<n;i++)
     78             for(j=0;j<m;j++)
     79             {
     80                 if(x[i][j])
     81                 {
     82                     g[x[i][j]][y[i][j]]=1;
     83                 }
     84             }
     85         
     86         
     87         for(i=0;i<n;i++)
     88         {
     89             for(j=0;j<m;j++)
     90             {
     91                 printf("%d ",x[i][j]);
     92             }
     93             printf("
    ");
     94         }
     95         for(i=0;i<n;i++)
     96         {
     97             for(j=0;j<m;j++)
     98             {
     99                 printf("%d ",y[i][j]);
    100             }
    101             printf("
    ");
    102         }
    103         
    104             
    105         //二分匹配
    106         memset(match,-1,sizeof(match));
    107         int ans=0;
    108         for(i=1;i<=xx;i++)
    109         {
    110             memset(vis,false,sizeof(vis));
    111             if(dfs(i))
    112                 ans++;
    113         }
    114 
    115         printf("Case :%d
    ",++ff);
    116         printf("%d
    ",ans);
    117     }
    118 }
    119 
    120 /*
    121 
    122 2
    123 5 5
    124 o***#
    125 *###*
    126 oo#oo
    127 ***#o
    128 #o**o
    129 4 4
    130 o***
    131 *###
    132 oo#o
    133 ***o
    134 
    135 */
    
    
  • 相关阅读:
    GCC内置函数
    父类子类的拷贝构造与赋值
    外传三 动态内存申请的结果
    外传二 函数的异常规格说明
    外传一 异常处理深度解析
    第69课 技巧,自定义内存管理
    第68课 拾遗,令人迷惑的写法
    第67课 经典问题解析五
    第66课 C++中的类型识别
    第65课 C++中的异常处理(下)
  • 原文地址:https://www.cnblogs.com/sweat123/p/4479113.html
Copyright © 2011-2022 走看看