一些二分匹配的题
/*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 */