1422

1 /*
2 求最小的路径覆盖
3
4 最小路径覆盖在数值上和 最大独立集是等价的
5
6 最小路径覆盖(二分图) = N - 最大匹配
7
8 在这题中,将每个十字路口拆成两点1' 1''
9
10 这样如果有两个十字路口之间有路 那么 1' -> 2''之间画线
11
12 这样就构成了一个二分图。现在题目要求,最小路径覆盖个数
13
14 如果没有连线,那么最大匹配就是0,则每个点都需要伞兵啦
15
16 如果有一个连线,那么最大匹配是1,则少用一个伞兵
17
18 同理,没增加一个匹配,则少一个伞兵,所以这样就容易理解了最小的路径覆盖和最大匹配之间的关系
19
20 */
21
22 // include file
23 #include <cstdio>
24 #include <cstdlib>
25 #include <cstring>
26 #include <cmath>
27 #include <cctype>
28 #include <ctime>
29
30 #include <iostream>
31 #include <sstream>
32 #include <fstream>
33 #include <iomanip>
34 #include <bitset>
35 #include <strstream>
36
37 #include <algorithm>
38 #include <string>
39 #include <vector>
40 #include <queue>
41 #include <set>
42 #include <list>
43 #include <functional>
44
45 using namespace std;
46
47 // typedef
48 typedef long long LL;
49 typedef unsigned long long ULL;
50
51 //
52 #define read freopen("in.txt","r",stdin)
53 #define write freopen("out.txt","w",stdout)
54 #define FORi(a,b,c) for(int i=(a);i<(b);i+=c)
55 #define FORj(a,b,c) for(int j=(a);j<(b);j+=c)
56 #define FORk(a,b,c) for(int k=(a);k<(b);k+=c)
57 #define FORp(a,b,c) for(int p=(a);p<(b);p+=c)
58
59 #define FF(i,a) for(int i=0;i<(a);i+++)
60 #define FFD(i,a) for(int i=(a)-1;i>=0;i--)
61 #define Z(a) (a<<1)
62 #define Y(a) (a>>1)
63
64 const double eps = 1e-6;
65 const double INFf = 1e10;
66 const int INFi = 1000000000;
67 const double Pi = acos(-1.0);
68
69 template<class T> inline T sqr(T a){return a*a;}
70 template<class T> inline T TMAX(T x,T y)
71 {
72 if(x>y) return x;
73 return y;
74 }
75 template<class T> inline T TMIN(T x,T y)
76 {
77 if(x<y) return x;
78 return y;
79 }
80 template<class T> inline void SWAP(T &x,T &y)
81 {
82 T t = x;
83 x = y;
84 y = t;
85 }
86 template<class T> inline T MMAX(T x,T y,T z)
87 {
88 return TMAX(TMAX(x,y),z);
89 }
90
91
92 // code begin
93
94 #define MAXN 150
95 vector<int> G[MAXN];
96 int mt[MAXN];
97 bool used[MAXN];
98 int T,N,M;
99
100 bool hungarian_MM(int i)
101 {
102 FORj(0,G[i].size(),1)
103 {
104 if(!used[ G[i][j] ])
105 {
106 used[ G[i][j] ] = true;
107 if( mt[G[i][j]]==-1 || hungarian_MM(mt[G[i][j]]))
108 {
109 mt[G[i][j]] = i;
110 return true;
111 }
112 }
113 }
114 return false;
115 }
116
117 int main()
118 {
119 read;
120 write;
121 int a,b,ans;
122 scanf("%d",&T);
123 while(T--)
124 {
125 scanf("%d %d",&N,&M);
126 FORi(1,N+1,1)
127 {
128 G[i].clear();
129 }
130
131 while(M--)
132 {
133 scanf("%d %d",&a,&b);
134 G[a].push_back(b);
135 }
136
137 ans = 0;
138 memset(mt,-1,sizeof(int)*MAXN);
139 FORi(1,N+1,1)
140 {
141 memset(used,0,sizeof(bool)*MAXN);
142 if( hungarian_MM(i) )
143 {
144 ans++;
145 }
146 }
147 printf("%d\n",N-ans);
148 }
149 return 0;
150 }
posted @ 2011-03-05 14:33  AC2012  阅读(724)  评论(0编辑  收藏  举报