二分图匹配详解(C++版)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
每个社团都需要选一个代表。谦哥希望更多的人能够成为代表。
输入描述Input Description
第一行输入两个数n和m。
以下n行每行若干个数,这些数都是不超过m的正整数。其中第i行的数表示社团i的全部成员。每行用一个0结束。
输出描述Output Description
输出最多的能够成为代表的人数。
对每组测试数据输出一行
仅有一个整数s
表示最多有多少个小杉能成功脱逃
Sample Input
1 1 Output
1
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int r,a,t;
inline int cal(int x,int y){return (x-1)*m+y;}
bool find(int x){
for(int i=1;i<=sum;i++)
if(map[x][i]&&!vis[i]){
vis[i]=1;
if(!res[i]||find(res[i]))return res[i]=x,1;
{
cp[i]=k;
return 1;
}
}
}
return 0;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>x;
while(x!=0)
{
a[i][x]=1;
cin>>x;
}
}
for(int i=1;i<=m;i++)
{
memset(old,0,sizeof(old));
}
return 0;
}
int main(){
scanf("%d%d%d",&n,&m,&k);sum=n*m;
for(int i=1;i<=n;i++)
二分图匹配
1、Way Selection(Vijos P1212)
描述Description
小杉家族r个人正在一片空地上散步,突然,外星人来了……
留给小杉家族脱逃的时间只有t秒,每个小杉都有一个跑的速度v
总共有a个传送点,小杉们必须在t秒内到达传送点才能脱逃
另外一个小杉进入一个传送点以后,该传送点就会消失
4 4
6
1 1
1 4
2 2
4 1
4 2
4 4
样例输出Sample Output
4
#include<cstdio>
#include<cstring>
int n,m,k,x,y,sum,ans;
int xx[4]={1,0,-1,0},yy[4]={0,1,0,-1},res[10010];
bool f[110][110],map[10010][10010],vis[10010];
样例输入Sample Input
4 4
1 2 0
1 2 0
1 2 0
1 2 3 4 0
样例输出Sample Output
3
数据范围及提示Data Size & Hint
各个测试点1s
数据范围
n,m<=200
#include<iostream>
#include<cstdio>
#include<cstring>
输入文件的第一行是两个整数N,M (1<=N,M<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N,1<=Y<=M)。
输出描述Output Description
输出所覆盖的最大面积块(1×2面积算一块)。
样例输入Sample Input
return 0;
}
bool find(int v)
{
for(int i=1;i<=a;i++)
if(mp[v][i]&&!y[i])
{
y[i]=1;
if(!lk[i]||find(lk[i]))
{
lk[i]=v;
return 1;
}
}
return 0;
}
int main()
{
double xx,yy,v;
using namespace std;
int n,m,x=1;
int a[210][210],old[210],cp[210];
bool find(int k)
{
for(int i=1;i<=n;i++)
{
if(a[i][k]==1&&old[i]==0)
{
old[i]=1;
if(cp[i]==0||find(cp[i]))
double px[1001],py[1001];
int lk[1001],y[1001],mp[1001][1001];
int ans=0;
bool pd(double x,double y,double v,int k)
{
if(v*t>=sqrt((x-px[k])*(x-px[k])+(y-py[k])*(y-py[k])))return 1;
cin>>r>>a>>t;
for(int i=1;i<=a;i++)
cin>>px[i]>>py[i];
for(int i=1;i<=r;i++)
{
cin>>xx>>yy>>v;
for(int j=1;j<=a;j++)
{
if(pd(xx,yy,v,j))mp[i][j]=1;
}
}
for(int i=1;i<=r;i++)
{
memset(y,0,sizeof(y));
if(find(i))ans++;
}
cout<<ans;
return 0;
}
2、寻找代表元(codevs2776)
题目描述Description
广州二中苏元实验学校一共有n个社团,分别用1到n编号。广州二中苏元实验学校一共有m个人,分别用1到m编号。每个人可以参加一个或多个社团,也可以不参加任何社团。
if(find(i)==1)x++;
}
cout<<x<<endl;
return 0;
}
3、覆盖
题目描述Description
有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。
输入描述Input Description
现在请你安排一种方案,使脱逃的小杉尽可能的多
输入格式Input Format
每组测试数据的
第一行有三个整数r和a和t(0<a,r,t<=1000)
第二行有a对实数,第i对数表示第i个传送点的坐标,这些坐标绝对值均不超过1e6
接下来r行,每行有三个实数x,y,v,表示第i个小杉的坐标和奔跑的速度
输出格式Output Format
输入描述Input Description
第一行输入两个数n和m。
以下n行每行若干个数,这些数都是不超过m的正整数。其中第i行的数表示社团i的全部成员。每行用一个0结束。
输出描述Output Description
输出最多的能够成为代表的人数。
对每组测试数据输出一行
仅有一个整数s
表示最多有多少个小杉能成功脱逃
Sample Input
1 1 Output
1
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int r,a,t;
inline int cal(int x,int y){return (x-1)*m+y;}
bool find(int x){
for(int i=1;i<=sum;i++)
if(map[x][i]&&!vis[i]){
vis[i]=1;
if(!res[i]||find(res[i]))return res[i]=x,1;
{
cp[i]=k;
return 1;
}
}
}
return 0;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>x;
while(x!=0)
{
a[i][x]=1;
cin>>x;
}
}
for(int i=1;i<=m;i++)
{
memset(old,0,sizeof(old));
}
return 0;
}
int main(){
scanf("%d%d%d",&n,&m,&k);sum=n*m;
for(int i=1;i<=n;i++)
二分图匹配
1、Way Selection(Vijos P1212)
描述Description
小杉家族r个人正在一片空地上散步,突然,外星人来了……
留给小杉家族脱逃的时间只有t秒,每个小杉都有一个跑的速度v
总共有a个传送点,小杉们必须在t秒内到达传送点才能脱逃
另外一个小杉进入一个传送点以后,该传送点就会消失
4 4
6
1 1
1 4
2 2
4 1
4 2
4 4
样例输出Sample Output
4
#include<cstdio>
#include<cstring>
int n,m,k,x,y,sum,ans;
int xx[4]={1,0,-1,0},yy[4]={0,1,0,-1},res[10010];
bool f[110][110],map[10010][10010],vis[10010];
样例输入Sample Input
4 4
1 2 0
1 2 0
1 2 0
1 2 3 4 0
样例输出Sample Output
3
数据范围及提示Data Size & Hint
各个测试点1s
数据范围
n,m<=200
#include<iostream>
#include<cstdio>
#include<cstring>
输入文件的第一行是两个整数N,M (1<=N,M<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N,1<=Y<=M)。
输出描述Output Description
输出所覆盖的最大面积块(1×2面积算一块)。
样例输入Sample Input
return 0;
}
bool find(int v)
{
for(int i=1;i<=a;i++)
if(mp[v][i]&&!y[i])
{
y[i]=1;
if(!lk[i]||find(lk[i]))
{
lk[i]=v;
return 1;
}
}
return 0;
}
int main()
{
double xx,yy,v;
using namespace std;
int n,m,x=1;
int a[210][210],old[210],cp[210];
bool find(int k)
{
for(int i=1;i<=n;i++)
{
if(a[i][k]==1&&old[i]==0)
{
old[i]=1;
if(cp[i]==0||find(cp[i]))
double px[1001],py[1001];
int lk[1001],y[1001],mp[1001][1001];
int ans=0;
bool pd(double x,double y,double v,int k)
{
if(v*t>=sqrt((x-px[k])*(x-px[k])+(y-py[k])*(y-py[k])))return 1;
cin>>r>>a>>t;
for(int i=1;i<=a;i++)
cin>>px[i]>>py[i];
for(int i=1;i<=r;i++)
{
cin>>xx>>yy>>v;
for(int j=1;j<=a;j++)
{
if(pd(xx,yy,v,j))mp[i][j]=1;
}
}
for(int i=1;i<=r;i++)
{
memset(y,0,sizeof(y));
if(find(i))ans++;
}
cout<<ans;
return 0;
}
2、寻找代表元(codevs2776)
题目描述Description
广州二中苏元实验学校一共有n个社团,分别用1到n编号。广州二中苏元实验学校一共有m个人,分别用1到m编号。每个人可以参加一个或多个社团,也可以不参加任何社团。
if(find(i)==1)x++;
}
cout<<x<<endl;
return 0;
}
3、覆盖
题目描述Description
有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。
输入描述Input Description
现在请你安排一种方案,使脱逃的小杉尽可能的多
输入格式Input Format
每组测试数据的
第一行有三个整数r和a和t(0<a,r,t<=1000)
第二行有a对实数,第i对数表示第i个传送点的坐标,这些坐标绝对值均不超过1e6
接下来r行,每行有三个实数x,y,v,表示第i个小杉的坐标和奔跑的速度
输出格式Output Format