题目链接:http://poj.org/problem?id=1325
题意:A机器有n个模式,B机器有m个模式,有k个任务,第i个任务可以用A机器的ai模式或者B机器的bi模式,换模式需要重启,开始两个机器都在模式0,问最少需要重启几次。
分析:
要求最小的重启次数,也就是求出除了0模式,最少要工作在几个模式
建图:A的模式为X集,B的模式为Y集,每个任务看做一条线,连接X集和Y集,则问题转化为求X、Y中最少的点,使得每条线至少有一个端点被选。即最小点集覆盖。
根据最小点集覆盖=二分图最大匹配。
代码:
1 #include <iostream>
2 #include <cstring>
3 #include <cstdio>
4 using namespace std;
5 const int N= 1001;
6 int map[N][N],vis[N],link[N];
7 int n1,n2,k;
8 int find( int x)
9 {
10 int i;
11 for(i= 1;i<=n2;i++)
12 {
13 if(map[x][i]&&!vis[i])
14 {
15 vis[i]= 1;
16 if(!link[i]||find(link[i]))
17 {
18 link[i]=x;
19 return 1;
20 }
21 }
22 }
23 return 0;
24 }
25 int main()
26 {
27 int a,b,c,i,sum;
28 while(~scanf( " %d ",&n1))
29 {
30 if(!n1)
31 break;
32 scanf( " %d%d ",&n2,&k);
33 sum= 0;
34 memset(map, 0, sizeof(map));
35 memset(link, 0, sizeof(link));
36 while(k--)
37 {
38 scanf( " %d%d%d ",&a,&b,&c);
39 if(b*c)
40 map[b][c]= 1;
41 }
42 for(i= 1;i<=n1;i++)
43 {
44 memset(vis, 0, sizeof(vis));
45 if(find(i))
46 sum++;
47 }
48 printf( " %d\n ",sum);
49 }
50 return 0;
51 }
2 #include <cstring>
3 #include <cstdio>
4 using namespace std;
5 const int N= 1001;
6 int map[N][N],vis[N],link[N];
7 int n1,n2,k;
8 int find( int x)
9 {
10 int i;
11 for(i= 1;i<=n2;i++)
12 {
13 if(map[x][i]&&!vis[i])
14 {
15 vis[i]= 1;
16 if(!link[i]||find(link[i]))
17 {
18 link[i]=x;
19 return 1;
20 }
21 }
22 }
23 return 0;
24 }
25 int main()
26 {
27 int a,b,c,i,sum;
28 while(~scanf( " %d ",&n1))
29 {
30 if(!n1)
31 break;
32 scanf( " %d%d ",&n2,&k);
33 sum= 0;
34 memset(map, 0, sizeof(map));
35 memset(link, 0, sizeof(link));
36 while(k--)
37 {
38 scanf( " %d%d%d ",&a,&b,&c);
39 if(b*c)
40 map[b][c]= 1;
41 }
42 for(i= 1;i<=n1;i++)
43 {
44 memset(vis, 0, sizeof(vis));
45 if(find(i))
46 sum++;
47 }
48 printf( " %d\n ",sum);
49 }
50 return 0;
51 }