一些二分匹配的题

/*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\n");
        else printf("NO\n");
    }
}






/**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\n"); else printf("NO\n"); } }
//最大独立集
//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",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\n",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\n",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\n");
54         else printf("Tom\n");
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("\n");
 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("\n");
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\n",++ff);
116         printf("%d\n",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 */

 


 

posted @ 2015-05-05 14:45  sweat123  阅读(138)  评论(0编辑  收藏  举报