HDU 2063
求一个二分图的最大匹配。
完全的裸题。贴代码。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
vector<int> G[1005];
bool check[1005];
int mac[1005];
int n;
void add_edge(int from,int to)
{
G[from].push_back(to);
G[to].push_back(from);
}
bool dfs(int u)
{
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(!check[v])
{
check[v]=1;
if(mac[v]==-1||dfs(mac[v]))
{
mac[u]=v;
mac[v]=u;
return 1;
}
}
}
return 0;
}
int xyl()
{
int ans=0;
memset(mac,-1,sizeof(mac));
for(int i=1;i<=n;i++)
{
if(mac[i]==-1)
{
memset(check,0,sizeof(check));
if(dfs(i))
{
ans++;
}
}
}
return ans;
}
int main()
{
int k,n1,m1;
while(scanf("%d",&k)!=EOF)
{
if(k==0) return 0;
scanf("%d%d",&n1,&m1);
n=n1+m1;
for(int i=1;i<=n;i++)
G[i].clear();
while(k--)
{
int A,B;
scanf("%d%d",&A,&B);
add_edge(A,B+n1);
}
printf("%d\n",xyl());
}
}
HDU 2444
判断该图是否为二分图,如果是二分图就求该图的最大匹配。
判断是否为二分图是我用了一个DFS 也不知道还有没有更简单的方法。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<stack>
#include<math.h>
#include<iostream>
using namespace std;
vector<int> G[205];
bool check[205];
int mac[205];
int re[205];
void add_edge(int from,int to)
{
G[from].push_back(to);
G[to].push_back(from);
}
bool rdfs(int u,int k)
{
re[u]=k;
bool flag=true;
int k1;
if(k==1) k1=2;
else k1=1;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(re[v]==k)
{
flag=false;
break;
}
else if(re[v]==0)
{
flag=rdfs(v,k1);
if(!flag)
break;
}
}
return flag;
}
bool dfs(int u)
{
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(!check[v])
{
check[v]=true;
if(mac[v]==-1||dfs(mac[v]))
{
mac[u]=v;
mac[v]=u;
return true;
}
}
}
return false;
}
int n;
int xyl()
{
int ans=0;
memset(mac,-1,sizeof(mac));
for(int i=1;i<=n;i++)
{
if(mac[i]==-1)
{
memset(check,0,sizeof(check));
check[i]=1;
if(dfs(i))
ans++;
}
}
return ans;
}
int main()
{
int m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
G[i].clear();
while(m--)
{
int A,B;
scanf("%d%d",&A,&B);
add_edge(A,B);
}
memset(re,0,sizeof(re));
bool flag=0;
for(int i=1;i<=n;i++)
{
if(re[i]==0)
{
if(!rdfs(i,1))
{
flag=1;
break;
}
}
}
if(flag==1) printf("No\n");
else
{
printf("%d\n",xyl());
}
}
}
HDU 1281
题意:一个棋盘上有一些地方能放“车” 求最多能放多少个,又有多少个点是关键点,关键点——删除这个点能放的“车”会变少。
把行归位X集合 列归为Y集合。每个点就是从X-Y的一条边。
进行二分图匹配。然后枚举边,求出删除这条边之后的最大匹配,如果比之前的少了 就是关键点。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
int mac[205];
bool check[205];
vector<int> G[205];
int z,y;
int n;
int k[10005][2];
void add_edge(int from,int to)
{
G[from].push_back(to);
G[to].push_back(from);
}
bool dfs(int u)
{
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if((u==z&&v==y)||(u==y&&v==z)) continue;
if(!check[v])
{
check[v]=1;
if(mac[v]==-1||dfs(mac[v]))
{
mac[u]=v;
mac[v]=u;
return true;
}
}
}
return false;
}
int xyl()
{
memset(mac,-1,sizeof(mac));
int ans=0;
for(int i=1;i<=n;i++)
{
if(mac[i]==-1)
{
memset(check,0,sizeof(check));
if(dfs(i))
ans++;
}
}
return ans;
}
int main()
{
int N,M,K;
int Case=0;
while(scanf("%d%d%d",&N,&M,&K)!=EOF)
{
for(int i=1;i<=N+M;i++)
G[i].clear();
int r=0;
n=N+M;
while(K--)
{
int A,B;
scanf("%d%d",&A,&B);
k[r][0]=A;
k[r][1]=B+N;
r++;
add_edge(A,B+N);
}
z=0;y=0;
int ans=xyl();
//printf("%d\n",ans);
int sum=0;
for(int i=0;i<r;i++)
{
z=k[i][0];
y=k[i][1];
int ans1=xyl();
if(ans1!=ans)
{
sum++;
}
}
printf("Board %d have %d important blanks for %d chessmen.\n",++Case,sum,ans);
}
}