有向图的二分匹配

http://info.zjfc.edu.cn/acm/problemDetail.aspx?pid=1483

 

这道题目是在比赛的时候做的,数据应该不大,所以直接暴力模拟了,赛后听学长讲正解是二分图的匹配,百思不得其解,不知如何构图,于是他点拨了一下,恍然大悟呀,发现思维灵活是何其得重要。

思路:这道题目要倒着想,假设 1 到 n 要放进柱子,最少要用几根柱子,二分匹配就是求柱子的数量的。其实可以当做是最小点覆盖= n - 最大匹配数,这道题目还有一个关键点,在标题中已经提到了,就是有向图,在放第 k 个球时,得保证 k-1 个已经放好了。所以再构图的时候需要注意。

 

贴下代码:

#include<stdio.h> #include<string.h> #include<math.h> int map[501][501],visited[501],match[501]; int dd[501]; int DFS(int v,int n) { int i; for(i=1;i<=n;i++){ if(!visited[i]&&map[v][i]){ visited[i]=1; if(!match[i]||DFS(match[i],n)){ match[i]=v; return 1; } } } return 0; } int main() { int i,j,k,sum,temp; memset(map,0,sizeof(map)); for(i=1;i<=500;i++){ for(j=i+1;j<=500;j++){ sum=i+j; temp=sqrt(sum*1.0); if(temp*temp==sum) map[i][j]=1; } }// 构图,可以思考一下为什么j是从i+1开始 for(i=1;i<=500;i++) map[i][i]=0; memset(dd,0,sizeof(dd)); for(k=1;k<=500;k++){ memset(match,0,sizeof(match)); for(i=1;i<=k;i++){ memset(visited,0,sizeof(visited)); DFS(i,k); }//传入一个k*k的图 int num=0; for(i=1;i<=k;i++) if(match[i]) num++;//统计k*k图的最大匹配数 dd[k]=k-num; } int n; while(scanf("%d",&n)!=EOF){ for(i=1;i<=500;i++){ if(dd[i]>n){ printf("%d/n",i-1);break; } } } return 0; }

你可能感兴趣的:(有向图的二分匹配)