1151: Air Raid

题目: http://acm.hdu.edu.cn/showproblem.php?pid=1151

有向无环图的最小路径覆盖
对于每个路口i,拆成i和i'
若存在一条道路从路口i通向路口j,则连边(i,j')
转化成二分图的最大匹配
二分图的匹配中,对于每一个点,只连一条边,与每路口不能有多人访问吻合
对于每个路口,存在一条入边一条出边;若只有入边或者出边表示这是一条路的端点
所以路的数量=(新图总点数-2*最大匹配数)/2=路口数-最大匹配数
用匈牙利算法求最大匹配
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 using namespace std;
 6 const int MaxN=1001;
 7 const int MaxM=100001;
 8 
 9 int n,m,ans,T;
10 int result[MaxN];
11 bool vis[MaxN];
12 bool a[2*MaxN][2*MaxN];
13 
14 void init()
15 {
16     scanf("%d%d",&n,&m);
17     for (int i=0;i<m;i++)
18     {
19         int x,y;
20         scanf("%d%d",&x,&y);
21         x--;
22         y--;
23         a[x][y+n]=1;
24     }
25 }
26 
27 bool find(int k)
28 {
29     for (int i=n;i<2*n;i++)
30     {
31         if (a[k][i]==1 && vis[i]==0//如果节点i与a相邻并且未被查找过
32         {
33             vis[i]=1//标记i为已查找过
34             if (result[i]==-1 || find(result[i])) //如果i未在前一个匹配M中 或者 i在匹配M中,但是从与i相邻的节点出发可以有增广路
35             {
36                 result[i]=k; //记录查找成功记录
37                 return 1//返回查找成功
38             }
39         }
40     }
41     return 0;
42 }
43 
44 int main()
45 {
46     for(scanf("%d",&T);T;T--)
47     {
48         ans=0;
49         memset(a,0,sizeof(a));
50         memset(result,-1,sizeof(result));
51         init();
52         for (int i=0;i<n;i++)
53         {
54             memset(vis,0,sizeof(vis)); //清空上次搜索时的标记
55             if (find(i)==1) ans++//从节点i尝试扩展
56         }
57         printf("%d\n",n-ans);
58     }
59     return 0;
60 }
61 
posted on 2012-10-05 10:55 Kiro 阅读(91) 评论(0)  编辑 收藏 引用 所属分类: hdu

只有注册用户登录后才能发表评论。
网站导航:   博客园   博客园最新博文   博问   管理