【二分图匹配专题】解题报告

HDU 1068 Girls and Boys

  男生和女生构成二分图,根据题目男女直接的暧昧关系求出最大匹配m,根据二分图的性质容易知道答案为n-m/2。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        10005
 31 #define MAXM        1000005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35  
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXN];
 40 
 41 int NE, head[MAXN];
 42 int n, m;
 43 int vis[MAXN], link[MAXN];
 44 
 45 void init()
 46 {
 47     NE = 0;
 48     memset(head, -1, sizeof(head));
 49     memset(link, -1, sizeof(link));
 50 }
 51 
 52 void add_edge(int u, int v)
 53 {
 54     E[NE].v = v;
 55     E[NE].next = head[u];
 56     head[u] = NE++;
 57 }
 58 
 59 int dfs(int u)
 60 {
 61     for(int i = head[u]; i != -1; i = E[i].next)
 62     {
 63         int v = E[i].v;
 64         if(!vis[v])
 65         {
 66             vis[v] = 1;
 67             if(link[v] == -1 || dfs(link[v]))
 68             {
 69                 link[v] = u;
 70                 return 1;
 71             }
 72         }
 73     }
 74     return 0;
 75 }
 76 int solve()
 77 {
 78     int ans = 0;
 79     rep(i,0,n-1)
 80     {
 81         clr(vis);
 82         ans += dfs(i);
 83     }
 84     return ans;
 85 }
 86 
 87 int main()
 88 {
 89     int a, b;
 90     while(scanf("%d", &n) != EOF)
 91     {
 92         init();
 93         rep(j,0,n-1)
 94         {
 95             scanf("%d: (%d)", &a, &m);
 96             rep(i,1,m)
 97             {
 98                 scanf("%d", &b);
 99                 add_edge(a, b);
100             }
101         }
102         printf("%d
", n - solve()/2);
103     }
104     return 0;
105 }
View Code

HDU 1150 Machine Schedule

  题目应该求的是二分图的最小点集覆盖,那么二分图的最小点集覆盖 = 最大匹配。(这条公式的证明可以参见Matrix67的博客

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        1005
 31 #define MAXM        100005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35  
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXN];
 40 
 41 int NE, head[MAXN];
 42 int n, m;
 43 int vis[MAXN], link[MAXN];
 44 
 45 void init()
 46 {
 47     NE = 0;
 48     memset(head, -1, sizeof(head));
 49     memset(link, -1, sizeof(link));
 50 }
 51 
 52 void add_edge(int u, int v)
 53 {
 54     E[NE].v = v;
 55     E[NE].next = head[u];
 56     head[u] = NE++;
 57 }
 58 
 59 int dfs(int u)
 60 {
 61     for(int i = head[u]; i != -1; i = E[i].next)
 62     {
 63         int v = E[i].v;
 64         if(!vis[v])
 65         {
 66             vis[v] = 1;
 67             if(link[v] == -1 || dfs(link[v]))
 68             {
 69                 link[v] = u;
 70                 return 1;
 71             }
 72         }
 73     }
 74     return 0;
 75 }
 76 int solve()
 77 {
 78     int ans = 0;
 79     rep(i,1,min(n, m))
 80     {
 81         clr(vis);
 82         ans += dfs(i);
 83     }
 84     return ans;
 85 }
 86 
 87 int main()
 88 {
 89     int a, b, c, k;
 90     while(scanf("%d", &n) != EOF)
 91     {
 92         if(n == 0) break;
 93         scanf("%d%d", &m, &k);
 94         init();
 95         rep(i, 0, k-1)
 96         {
 97             scanf("%d%d%d", &a, &b, &c);
 98             add_edge(b, c+n);
 99             add_edge(c+n, b);
100         }
101         printf("%d
", solve());
102     }
103     return 0;
104 }
View Code


 

HDU 1179 Ollivanders: Makers of Fine Wands since 382 BC.

  题目很长,模型很裸。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        1005
 31 #define MAXM        100005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35  
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m;
 43 int vis[MAXN], link[MAXN];
 44 
 45 void init()
 46 {
 47     NE = 0;
 48     memset(head, -1, sizeof(head));
 49     memset(link, -1, sizeof(link));
 50 }
 51 
 52 void add_edge(int u, int v)
 53 {
 54     E[NE].v = v;
 55     E[NE].next = head[u];
 56     head[u] = NE++;
 57 }
 58 
 59 int dfs(int u)
 60 {
 61     for(int i = head[u]; i != -1; i = E[i].next)
 62     {
 63         int v = E[i].v;
 64         if(!vis[v])
 65         {
 66             vis[v] = 1;
 67             if(link[v] == -1 || dfs(link[v]))
 68             {
 69                 link[v] = u;
 70                 return 1;
 71             }
 72         }
 73     }
 74     return 0;
 75 }
 76 int solve()
 77 {
 78     int ans = 0;
 79     rep(i,1,n)
 80     {
 81         clr(vis);
 82         ans += dfs(i);
 83     }
 84     return ans;
 85 }
 86 
 87 int main()
 88 {
 89     int b, k;
 90     while(scanf("%d%d", &n, &m) != EOF)
 91     {
 92         init();
 93         rep(i,1,m)
 94         {
 95             scanf("%d", &k);
 96             rep(j,1,k)
 97             {
 98                 scanf("%d", &b);
 99                 add_edge(i,b);
100             }
101         }
102         printf("%d
", solve());
103     }
104     return 0;
105 }
View Code

HDU 1281 棋盘游戏

  典型的行列匹配,第一问比较好解决,二分图最大匹配就是了。对于第二问,逐个删去棋盘的位置看最大匹配是否改变,如果改变了,那么这点就是关键点,否则不是。

  关于行列匹配,为什么能够用二分图解决,我是这么想的:这用最小点集覆盖模型来说明会更清楚一些,那么对于这道题来说,如果一行放了一个“車”,相当于这个格子所在的行列都被这点覆盖了。

  我这个代码用邻接表写的,运行时间有点儿长,用邻接矩阵写能0ms。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        50005
 31 #define MAXM        1000005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35  
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m, k;
 43 int vis[MAXN], link[MAXN];
 44 int x[MAXN], y[MAXN];
 45 
 46 void init()
 47 {
 48     NE = 0;
 49     memset(head, -1, sizeof(head));
 50     memset(link, -1, sizeof(link));
 51 }
 52 
 53 void add_edge(int u, int v)
 54 {
 55     E[NE].v = v;
 56     E[NE].next = head[u];
 57     head[u] = NE++;
 58 }
 59 
 60 int dfs(int u)
 61 {
 62     for(int i = head[u]; i != -1; i = E[i].next)
 63     {
 64         int v = E[i].v;
 65         if(!vis[v])
 66         {
 67             vis[v] = 1;
 68             if(link[v] == -1 || dfs(link[v]))
 69             {
 70                 link[v] = u;
 71                 return 1;
 72             }
 73         }
 74     }
 75     return 0;
 76 }
 77 int solve()
 78 {
 79     int ans = 0;
 80     rep(i,1,n)
 81     {
 82         clr(vis);
 83         ans += dfs(i);
 84     }
 85     return ans;
 86 }
 87 
 88 int main()
 89 {
 90     int cas = 1;
 91     while(scanf("%d%d%d", &n, &m, &k) != EOF)
 92     {
 93         
 94         rep(i,1,k)
 95             scanf("%d%d", &x[i], &y[i]);
 96             
 97         init();
 98         rep(i,1,k)
 99             add_edge(x[i], y[i]);
100             
101         int ans2 = solve(), ans1 = 0;   
102         rep(p,1,k)
103         {
104             init();
105             rep(i,1,k)
106             {
107                 if(i == p) continue;
108                 add_edge(x[i], y[i]);
109             }
110             if(solve() != ans2)
111                 ans1++;
112         }
113         printf("Board %d have %d important blanks for %d chessmen.
", cas++, ans1, ans2);
114     }
115     return 0;
116 }
View Code

HDU 1498 50 years, 50 colors

  枚举每一种颜色,用最大匹配和k比较一下就好了。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        50005
 31 #define MAXM        1000005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35  
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m, k;
 43 int vis[MAXN], link[MAXN];
 44 int x[MAXN], y[MAXN];
 45 
 46 void init()
 47 {
 48     NE = 0;
 49     memset(head, -1, sizeof(int)*105);
 50     memset(link, -1, sizeof(int)*105);
 51 }
 52 
 53 void add_edge(int u, int v)
 54 {
 55     E[NE].v = v;
 56     E[NE].next = head[u];
 57     head[u] = NE++;
 58 }
 59 
 60 int dfs(int u)
 61 {
 62     for(int i = head[u]; i != -1; i = E[i].next)
 63     {
 64         int v = E[i].v;
 65         if(!vis[v])
 66         {
 67             vis[v] = 1;
 68             if(link[v] == -1 || dfs(link[v]))
 69             {
 70                 link[v] = u;
 71                 return 1;
 72             }
 73         }
 74     }
 75     return 0;
 76 }
 77 int solve()
 78 {
 79     int ans = 0;
 80     rep(i,1,n)
 81     {
 82         clr(vis);
 83         ans += dfs(i);
 84         
 85     }
 86     return ans;
 87 }
 88 
 89 int ans[MAXN], cnt;
 90 int color[105][105];
 91 int h[55];
 92 int main()
 93 {
 94     while(scanf("%d%d", &n, &k) != EOF && n + m)
 95     {
 96         clr(h);
 97         rep(i,1,n)
 98             rep(j,1,n)
 99             {
100                 scanf("%d", &color[i][j]);
101                 if(!h[color[i][j]])
102                     h[color[i][j]] = 1;
103             }
104                 
105         cnt = 0;
106         rep(p,1,50)
107         {
108             if(!h[p]) continue;
109             init();
110             rep(i,1,n) 
111             {
112                 rep(j,1,n)
113                 {
114                     if(color[i][j] == p)
115                     {
116                         add_edge(i, j);
117                     }
118                 }
119             }
120             if(solve() > k)
121                 ans[cnt++] = p;
122         }
123         if(cnt == 0)
124             printf("-1
");
125         else
126         {
127             rep(i,0,cnt-1)
128             {
129                 if(i != 0) putchar(' ');
130                 printf("%d", ans[i]);
131             }
132             printf("
");
133         }
134     }
135     return 0;
136 }
View Code

HDU 1507 Uncle Tom's Inherited Land*

  相邻的两个空白点连边,我建的是双向边,那么最终的最大匹配要除以2,link数组记录了每个节点的连接点。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        10005
 31 #define MAXM        400005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35  
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m, k;
 43 bool vis[MAXN];
 44 int link[MAXN];
 45 int a, b;
 46 bool g[105][105];
 47 bool h[MAXN];
 48 
 49 void init()
 50 {
 51     NE = 0;
 52     memset(head, -1, sizeof head);
 53     memset(link, -1, sizeof link);
 54 }
 55 
 56 void add_edge(int u, int v)
 57 {
 58     E[NE].v = v;
 59     E[NE].next = head[u];
 60     head[u] = NE++;
 61 }
 62 
 63 int dfs(int u)
 64 {
 65     for(int i = head[u]; i != -1; i = E[i].next)
 66     {
 67         int v = E[i].v;
 68         if(!vis[v])
 69         {
 70             vis[v] = 1;
 71             if(link[v] == -1 || dfs(link[v]))
 72             {
 73                 link[v] = u;
 74                 return 1;
 75             }
 76         }
 77     }
 78     return 0;
 79 }
 80 int solve()
 81 {
 82     int ans = 0;
 83     rep(i,1,n*m)
 84     {
 85         clr(vis);
 86         ans += dfs(i);
 87         
 88     }
 89     return ans;
 90 }
 91 
 92 
 93 
 94 int main()
 95 {
 96     while(scanf("%d%d", &n, &m) != EOF && (n||m))
 97     {
 98         scanf("%d", &k);
 99         init();
100         clr(g);
101         rep(i,1,k)
102         {
103             scanf("%d%d", &a, &b);
104             g[a][b] = true;
105         }
106         rep(i,1,n)
107         {
108             rep(j,1,m)
109             {
110                 if(g[i][j]) continue;
111                 int x = j, y = i-1;
112                 if(y >= 1 && !g[y][x])
113                 {
114                     add_edge(j+(i-1)*m, x+(y-1)*m);
115                     add_edge(x+(y-1)*m, j+(i-1)*m);
116                 }
117                 x = j-1, y = i;
118                 if(x >= 1 && !g[y][x])
119                 {
120                     add_edge(j+(i-1)*m, x+(y-1)*m);
121                     add_edge(x+(y-1)*m, j+(i-1)*m);
122                 }
123             }
124         }
125         
126         printf("%d
", solve()/2);
127         
128         clr(h);
129         rep(i,1,n*m)
130         {
131             if(link[i] != -1 && !h[i] && !h[link[i]])
132             {
133                 printf("(%d,%d)--(%d,%d)
", (i-1)/m+1, i%m==0?m:i%m, (link[i]-1)/m+1, link[i]%m==0?m:link[i]%m);
134                 h[i] = h[link[i]] = true;
135             }
136         }
137         printf("
");
138     }
139     return 0;
140 }
View Code

HDU 1528 Card Game Cheater

  Eve能赢的牌就连一条边,然后求最大匹配就好了。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        10005
 31 #define MAXM        400005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35 
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m, k;
 43 bool vis[MAXN];
 44 int link[MAXN];
 45 char A[MAXN][5], B[MAXN][5];
 46 
 47 void init()
 48 {
 49     NE = 0;
 50     memset(head, -1, sizeof head);
 51     memset(link, -1, sizeof link);
 52 }
 53 
 54 void add_edge(int u, int v)
 55 {
 56     E[NE].v = v;
 57     E[NE].next = head[u];
 58     head[u] = NE++;
 59 }
 60 
 61 int dfs(int u)
 62 {
 63     for(int i = head[u]; i != -1; i = E[i].next)
 64     {
 65         int v = E[i].v;
 66         if(!vis[v])
 67         {
 68             vis[v] = 1;
 69             if(link[v] == -1 || dfs(link[v]))
 70             {
 71                 link[v] = u;
 72                 return 1;
 73             }
 74         }
 75     }
 76     return 0;
 77 }
 78 int solve()
 79 {
 80     int ans = 0;
 81     rep(i,1,n)
 82     {
 83         clr(vis);
 84         ans += dfs(i);
 85     }
 86     return ans;
 87 }
 88 
 89 
 90 
 91 int main()
 92 {
 93     int t;
 94     scanf("%d", &t);
 95     while(t--)
 96     {
 97         scanf("%d", &n);
 98         rep(i,1,n)
 99         {
100             scanf("%s", A[i]);
101             if(A[i][0] == 'T') A[i][0] = '9'+1;
102             if(A[i][0] == 'J') A[i][0] = '9'+2;
103             if(A[i][0] == 'Q') A[i][0] = '9'+3;
104             if(A[i][0] == 'K') A[i][0] = '9'+4;
105             if(A[i][0] == 'A') A[i][0] = '9'+5;
106             if(A[i][1] == 'C') A[i][1] = 'a';
107             if(A[i][1] == 'D') A[i][1] = 'b';
108             if(A[i][1] == 'S') A[i][1] = 'c';
109             if(A[i][1] == 'H') A[i][1] = 'd';
110         }
111         rep(i,1,n)
112         {
113             scanf("%s", B[i]);
114             if(B[i][0] == 'T') B[i][0] = '9'+1;
115             if(B[i][0] == 'J') B[i][0] = '9'+2;
116             if(B[i][0] == 'Q') B[i][0] = '9'+3;
117             if(B[i][0] == 'K') B[i][0] = '9'+4;
118             if(B[i][0] == 'A') B[i][0] = '9'+5;
119             if(B[i][1] == 'C') B[i][1] = 'a';
120             if(B[i][1] == 'D') B[i][1] = 'b';
121             if(B[i][1] == 'S') B[i][1] = 'c';
122             if(B[i][1] == 'H') B[i][1] = 'd';
123         }
124         init();
125         rep(i,1,n)
126             rep(j,1,n)
127                 if(B[i][0] > A[j][0] || (B[i][0] == A[j][0] && B[i][1] > A[j][1]))
128                     add_edge(i, j);
129         printf("%d
", solve());
130     }
131     return 0;
132 }
View Code

HDU 1845 Jimmy’s Assignment

  感觉是一个坑啊,我的写TLE了,下面是我师兄的二分图匹配AC代码,也跑了900+ms。其实答案是n/2!

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<stack>
 6 #include<string.h>
 7 #include<queue>
 8 #define ll long long
 9 #define esp 1e-5
10 #define MAXN 5006
11 #define MAXM 100005
12 #define oo 100000007
13 using namespace std;   
14 struct node
15 {
16        int y,next;
17 }line[MAXM];
18 int Lnum,_next[MAXN],match[MAXN];
19 bool used[MAXN];
20 void addline(int x,int y)
21 {
22        line[++Lnum].next=_next[x],_next[x]=Lnum,line[Lnum].y=y;
23 }
24 bool dfs(int x)
25 {
26        for (int k=_next[x];k;k=line[k].next)
27        {
28                int y=line[k].y;
29                if (used[y]) continue;
30                used[y]=true;
31                if (!match[y] || dfs(match[y]))
32                {
33                       match[y]=x;
34                       return true;
35                }
36        }
37        return false;
38 }
39 int getmax(int n)
40 {
41        int sum=0;
42        memset(match,0,sizeof(match));
43        for (int i=1;i<=n;i++)
44            {
45                  memset(used,false,sizeof(used));
46                  sum+=dfs(i);
47            }
48        return sum;
49 }
50 int main()
51 {            
52        int cases,i,n,m;     
53        scanf("%d",&cases);
54        while (cases--)
55        {
56                 scanf("%d",&n);
57                 m=3*n/2;
58                 Lnum=0,memset(_next,0,sizeof(_next));
59                 for (i=1;i<=m;i++)
60                 {
61                        int x,y;
62                        scanf("%d%d",&x,&y);
63                        addline(x,y),addline(y,x);
64                 }
65                 printf("%d
",getmax(n)/2);                
66        }
67        return 0;  
68 }  
View Code

HDU 2444 The Accomodation of Students

  求二分图最大匹配,如果有一个人不能匹配,就输出"NO";如果全部都能得到匹配,输出最大匹配。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #pragma comment(linker, "/STACK:102400000,102400000")
 25 #define pii         pair<int,int>
 26 #define clr(a)      memset((a),0,sizeof (a))
 27 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 28 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 29 #define inf         (0x3f3f3f3f)
 30 #define eps         1e-6
 31 #define MAXN        505
 32 #define MAXM        400005
 33 #define MODN        (1000000007)
 34 #define test        puts("reach here");
 35 typedef long long LL;
 36 
 37 struct Node
 38 {
 39     int v, next;
 40 }E[MAXM];
 41 
 42 int NE, head[MAXN];
 43 int n, m, k;
 44 bool vis[MAXN];
 45 int link[MAXN];
 46 int color[MAXN];
 47 
 48 void init()
 49 {
 50     NE = 0;
 51     clr(color);
 52     memset(head, -1, sizeof head);
 53     memset(link, -1, sizeof link);
 54 }
 55 
 56 void add_edge(int u, int v)
 57 {
 58     E[NE].v = v;
 59     E[NE].next = head[u];
 60     head[u] = NE++;
 61 }
 62 
 63 int dfs(int u)
 64 {
 65     for(int i = head[u]; i != -1; i = E[i].next)
 66     {
 67         int v = E[i].v;
 68         if(!vis[v])
 69         {
 70             vis[v] = 1;
 71             if(link[v] == -1 || dfs(link[v]))
 72             {
 73                 link[v] = u;
 74                 return 1;
 75             }
 76         }
 77     }
 78     return 0;
 79 }
 80 
 81 int solve()
 82 {
 83     int ans = 0;
 84     rep(i,1,n)
 85     {
 86         clr(vis);
 87         ans += dfs(i);
 88     }
 89     return ans;
 90 }
 91 
 92 bool dfs1(int u, int fa, int d)
 93 {
 94     int c = (d&1) ? 1 : 2;
 95     if((c == 1 && color[u] == 2 )|| (c == 2 && color[u] == 1))
 96         return false;
 97     if(color[u])
 98         return true;
 99     color[u] = c;
100     for(int i = head[u]; i != -1; i = E[i].next)
101     {
102         int v = E[i].v;
103         if(v == fa) continue;
104         if(!dfs1(v, u, d+1))
105             return false;
106     }
107     return true;
108 }
109 
110 int main()
111 {
112     while(scanf("%d%d", &n, &m) != EOF)
113     {
114         init();
115         rep(i,1,m)
116         {
117             int a, b;
118             scanf("%d%d", &a, &b);
119             add_edge(a, b);
120             add_edge(b, a);
121         }
122         bool flag = true;
123         rep(i,1,n)
124             if(!color[i])
125                 if(!dfs1(i, -1, 0))
126                     flag = false;
127         if(flag)
128             printf("%d
", solve()/2);
129         else
130             printf("No
");
131     }
132     return 0;
133 }
View Code

HDU 2768 Cat vs. Dog

  一路刷题下来到这题,可以得出这道题是水题了。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        505
 31 #define MAXM        400005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35 
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m, k;
 43 bool vis[MAXN];
 44 int link[MAXN];
 45 char a[MAXN][5], b[MAXN][5];
 46 
 47 void init()
 48 {
 49     NE = 0;
 50     memset(head, -1, sizeof head);
 51     memset(link, -1, sizeof link);
 52 }
 53 
 54 void add_edge(int u, int v)
 55 {
 56     E[NE].v = v;
 57     E[NE].next = head[u];
 58     head[u] = NE++;
 59 }
 60 
 61 int dfs(int u)
 62 {
 63     for(int i = head[u]; i != -1; i = E[i].next)
 64     {
 65         int v = E[i].v;
 66         if(!vis[v])
 67         {
 68             vis[v] = 1;
 69             if(link[v] == -1 || dfs(link[v]))
 70             {
 71                 link[v] = u;
 72                 return 1;
 73             }
 74         }
 75     }
 76     return 0;
 77 }
 78 
 79 int solve()
 80 {
 81     int ans = 0;
 82     rep(i,1,n)
 83     {
 84         clr(vis);
 85         ans += dfs(i);
 86     }
 87     return ans;
 88 }
 89 
 90 
 91 // 最大独立集 = 顶点个数 - 最小顶点覆盖(最大匹配)
 92 int main()
 93 {
 94     int t, c, d;
 95     scanf("%d", &t);
 96     while(t--)
 97     {
 98         scanf("%d%d%d", &c, &d, &n);
 99         rep(i,1,n)
100             scanf("%s%s", a[i], b[i]);
101         init();
102         rep(i,1,n)
103         {
104             rep(j,i+1,n)
105             {
106                 if(strcmp(a[i],b[j]) == 0 || strcmp(b[i], a[j]) == 0)
107                 {
108                     //printf("i = %d   j = %d
", )
109                     add_edge(i, j);
110                     add_edge(j, i);
111                 }
112             }
113         }
114         printf("%d
", n - solve()/2);
115     }
116     return 0;
117 }
View Code

HDU 3360 National Treasures

  貌似看题就看了老半天。

  由于珠宝的临界点必须放置守卫,一个守卫又有可能同时保护许多个珠宝,发现最后要求的便是二分图的最小点集覆盖,这个二分图是这样建的:对于每一个珠宝,如果其临界点没有守卫,那么就在珠宝和该临界点之间连一条边,这条边是必须被覆盖的,所以当整个二分图所有的边都连好后,所要做的就是求最小点集覆盖。

  我看到网上很多人的做法有奇偶染色的,没搞明白,我这里写简单了一点,直接建成无向图,那么最终计算得到的为最小点集覆盖的2倍。注意这道题的方向问题,表示我自己上下左右都不分了QAQ。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <algorithm>
  9 #include <sstream>
 10 #include <iostream>
 11 #include <iomanip>
 12 #include <cstdio>
 13 #include <cstdlib>
 14 #include <cstring>
 15 #include <queue>
 16 using namespace std;
 17 #define pii         pair<int,int>
 18 #define clr(a)      memset((a),0,sizeof (a))
 19 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 20 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 21 #define inf         (0x3f3f3f3f)
 22 #define eps         1e-6
 23 #define MAXN        5005
 24 #define MAXM        1000005
 25 #define MODN        1000000007
 26 #define debug       puts("reach here")
 27 #define MP          make_pair
 28 #define PB          push_back
 29 #define RI(x)       scanf("%d",&x)
 30 #define RII(x,y)    scanf("%d%d",&x,&y)
 31 #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
 32 typedef long long LL;
 33 
 34 struct Node
 35 {
 36     int v, next;
 37 }E[MAXM];
 38 
 39 int NE, head[MAXN];
 40 bool vis[MAXN];
 41 int link[MAXN];
 42 int n, m;
 43 int R, C;
 44 int g[55][55];
 45 int dy[12]={-1,-2,-2,-1,1,2, 2, 1,-1,0,1, 0};
 46 int dx[12]={-2,-1, 1, 2,2,1,-1,-2, 0,1,0,-1};
 47 void add_edge(int u, int v)
 48 {
 49     E[NE].v = v;
 50     E[NE].next = head[u];
 51     head[u] = NE++;
 52 }
 53 void init()
 54 {
 55     NE = 0;
 56     memset(head, -1, sizeof head);
 57 }
 58 
 59 int dfs(int u)
 60 {
 61     for(int i = head[u]; i != -1; i = E[i].next)
 62     {
 63         int v = E[i].v;
 64         if(!vis[v])
 65         {
 66             vis[v] = 1;
 67             if(link[v] == -1 || dfs(link[v]))
 68             {
 69                 link[v] = u;
 70                 return 1;
 71             }
 72         }
 73     }
 74     return 0;
 75 }
 76 
 77 int solve()
 78 {
 79     int ans = 0;
 80     memset(link, -1, sizeof link);
 81     rep(i,1,R)
 82     {
 83         rep(j,1,C)
 84         {
 85             if((i+j)&1)
 86             {
 87                 clr(vis);
 88                 ans += dfs(j+(i-1)*C);
 89             }
 90         }
 91     }
 92     return ans;
 93 }
 94 
 95 int main()
 96 {
 97     int cas = 1;
 98     while(RII(R,C) != EOF)
 99     {
100         if(R == 0 && C == 0) break;
101         init();
102         rep(i,1,R)
103             rep(j,1,C)
104                 RI(g[i][j]);
105         rep(i,1,R)
106         {
107             rep(j,1,C)
108             {
109                 if(g[i][j] == -1) continue;
110                 rep(k,0,11)
111                 {
112                     if((g[i][j] >> k) & 1)
113                     {
114                         int x = j + dx[k];
115                         int y = i + dy[k];
116                         if(x >= 1 && x <= C && y >= 1 && y <= R && g[y][x] != -1)
117                         {
118                             if((i+j)&1)
119                                 add_edge(j + (i-1) * C, x + (y-1) * C);
120                             else
121                                 add_edge(x + (y-1) * C, j + (i-1) * C);
122                         }
123                     }
124                 }
125             }
126         }
127         printf("%d. %d
", cas++, solve());
128     }
129     return 0;
130 }
View Code

HDU 1045 Fire Net

  分别对行和列进行编号,拿行来说,连续的一串空白格子编同一个行号,对列同理。编好号之后做行列匹配。如下图:

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        505
 31 #define MAXM        400005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35 
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m, k;
 43 bool vis[MAXN];
 44 int link[MAXN];
 45 char g[10][10];
 46 int row[10][10];
 47 int col[10][10];
 48 int rc, cc;
 49 void init()
 50 {
 51     NE = 0;
 52     memset(head, -1, sizeof head);
 53     memset(link, -1, sizeof link);
 54 }
 55 
 56 void add_edge(int u, int v)
 57 {
 58     E[NE].v = v;
 59     E[NE].next = head[u];
 60     head[u] = NE++;
 61 }
 62 
 63 int dfs(int u)
 64 {
 65     for(int i = head[u]; i != -1; i = E[i].next)
 66     {
 67         int v = E[i].v;
 68         if(!vis[v])
 69         {
 70             vis[v] = 1;
 71             if(link[v] == -1 || dfs(link[v]))
 72             {
 73                 link[v] = u;
 74                 return 1;
 75             }
 76         }
 77     }
 78     return 0;
 79 }
 80 
 81 int solve()
 82 {
 83     int ans = 0;
 84     rep(i,0,rc-1)
 85     {
 86         clr(vis);
 87         ans += dfs(i);
 88     }
 89     return ans;
 90 }
 91 
 92 int main()
 93 {
 94     while(scanf("%d", &n) != EOF && n)
 95     {
 96         rep(i,0,n-1)
 97             scanf("%s", g[i]);
 98         
 99         memset(row, -1, sizeof row);
100         memset(col, -1, sizeof col);
101         rc = cc = 0;
102         rep(i,0,n-1)
103         {
104             rep(j,0,n-1)
105             {
106                 if(g[i][j] == '.' && row[i][j] == -1)
107                 {
108                     for(int k = j; k < n && g[i][k] == '.'; k++)
109                         row[i][k] = rc;
110                     rc++;
111                 }
112                 if(g[i][j] == '.' && col[i][j] == -1)
113                 {
114                     for(int k = i; k < n && g[k][j] == '.'; k++)
115                         col[k][j] = cc;
116                     cc++;
117                 }
118             }
119         }
120         init();
121         rep(i,0,n-1)
122         {
123             rep(j,0,n-1)
124             {
125                 if(g[i][j] == '.')
126                     add_edge(row[i][j], col[i][j]);
127             }
128         }
129         printf("%d
", solve());
130     }
131     return 0;
132 }
View Code

HDU 3118 Arbiter

  有没有人和我一样玩SC2的呀?给我留个信息一起玩撒^_^

  回到正题,题目意思就是要我们去掉最少的边使得整个图不包含奇圈,对于每一条边,两个顶点必须位于不同的集合,否则这条边是要去掉的边。由于n只有15,直接进行二进制状态枚举,对于每一个状态判断两个顶点是否在不同的集合即可。

 1 #include <vector>
 2 #include <list>
 3 #include <map>
 4 #include <set>
 5 #include <queue>
 6 #include <deque>
 7 #include <stack>
 8 #include <bitset>
 9 #include <algorithm>
10 #include <functional>
11 #include <numeric>
12 #include <utility>
13 #include <sstream>
14 #include <iostream>
15 #include <iomanip>
16 #include <cstdio>
17 #include <cmath>
18 #include <cstdlib>
19 #include <cstring>
20 #include <ctime>
21 #include <queue>
22 #include <cassert>
23 using namespace std;
24 #define pii         pair<int,int>
25 #define clr(a)      memset((a),0,sizeof (a))
26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
28 #define inf         (0x3f3f3f3f)
29 #define eps         1e-6
30 #define MAXN        305
31 #define MAXM        400005
32 #define MODN        (1000000007)
33 #define test        puts("reach here");
34 typedef long long LL;
35 
36 int n, m;
37 int p[MAXN][2];
38 
39 int main()
40 {
41     int t;
42     scanf("%d", &t);
43     while(t--)
44     {
45         scanf("%d%d", &n, &m);
46         rep(i,0,m-1)
47             scanf("%d%d", &p[i][0], &p[i][1]);
48         int ans = inf;
49         rep(i,0,1<<n)
50         {
51             int cnt = 0;
52             rep(j,0,m-1)
53                 if(((i>>p[j][0])&1) == ((i>>p[j][1])&1))
54                     cnt++;
55             ans = min(ans, cnt);
56         }
57         printf("%d
", ans);
58     }
59     return 0;
60 }
View Code

HDU 3729 I'm Telling the Truth

  将分数区间离散化,每一个学生和其对应的区间的每一个分数连边,求出最大匹配并记录解即可。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        100005
 31 #define MAXM        4000005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35 
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m, k;
 43 bool vis[MAXN];
 44 int link[MAXN];
 45 int p[MAXN]; 
 46 
 47 void init()
 48 {
 49     NE = 0;
 50     memset(head, -1, sizeof head);
 51     memset(link, -1, sizeof link);
 52 }
 53 
 54 void add_edge(int u, int v)
 55 {
 56     E[NE].v = v;
 57     E[NE].next = head[u];
 58     head[u] = NE++;
 59 }
 60 
 61 int dfs(int u)
 62 {
 63     for(int i = head[u]; i != -1; i = E[i].next)
 64     {
 65         int v = E[i].v;
 66         if(!vis[v])
 67         {
 68             vis[v] = 1;
 69             if(link[v] == -1 || dfs(link[v]))
 70             {
 71                 link[v] = u;
 72                 return 1;
 73             }
 74         }
 75     }
 76     return 0;
 77 }
 78 
 79 int solve()
 80 {
 81     int ans = 0;
 82     per(i,n,1)
 83     {
 84         clr(vis);
 85         if(dfs(i))
 86             p[ans++] = i;
 87     }
 88     return ans;
 89 }
 90 
 91 
 92 int main()
 93 {
 94     int t, a, b;
 95     scanf("%d", &t);
 96     while(t--)
 97     {
 98         scanf("%d", &n);
 99         init();
100         rep(i,1,n)
101         {
102             scanf("%d%d", &a, &b);
103             rep(j,a,b)
104                 add_edge(i,j);
105         }
106         int ans = solve();
107         printf("%d
", ans);
108         per(i,ans-1,0)
109         {
110             printf("%d", p[i]);
111             if(i != 0) putchar(' ');
112         }
113         putchar('
');
114     }
115     return 0;
116 }
View Code

HDU 2389 Rain on your Parade

  建图很容易,但是发现边的数量达到了惊人的9000000,普通的匈牙利毫无疑问地TLE了。后来才发现,有一种改进的匈牙利算法——HK算法,其思想是在每一次找增广路的时候不是只找一条,而是多条(这和网络流dinic算法思想类似),据说复杂度优化到了O(n^0.5*m)。

  1 #include <iostream>
  2 #include <math.h>
  3 #include <vector>
  4 #include <queue>
  5 #include <stack>
  6 #include <stdio.h>
  7 #include <string.h>
  8 #include <algorithm>
  9 using namespace std;
 10 
 11 const int N=3010;
 12 struct cor
 13 {
 14     int x,y;
 15 }X[N],Y[N];
 16 int speed[N];
 17 bool visit[N];
 18 int cx[N],cy[N];
 19 int dx[N],dy[N];
 20 
 21 vector <int> G[N];
 22 double dis(int i,int j)
 23 {
 24    return sqrt(double( (X[i].x-Y[j].x)*(X[i].x-Y[j].x) + (X[i].y-Y[j].y)*(X[i].y-Y[j].y) ) );
 25 }
 26 int m,n;
 27 bool search()
 28 {
 29     memset(dx,0,sizeof(dx));
 30     memset(dy,0,sizeof(dy));
 31     queue <int > Q;
 32     int i,u,v;
 33     bool flag=0;
 34 
 35     for(i=1;i<=m;i++)
 36      if(!cx[i]) Q.push(i);
 37 
 38     while(!Q.empty())
 39     {
 40         u=Q.front();Q.pop();
 41         for(i=0;i<G[u].size();i++)
 42         {
 43             v=G[u][i];
 44             if(!dy[v])
 45             {
 46                 dy[v]=dx[u]+1;
 47                 if(!cy[v])
 48                    flag=true;
 49                 else
 50                 {
 51                    dx[cy[v]]=dy[v]+1;
 52                    Q.push(cy[v]);
 53                 }
 54             }
 55         }
 56     }
 57     return flag;
 58 }
 59 bool dfs(int u)
 60 {
 61     int i,v;
 62     for(i=0;i<G[u].size();i++)
 63      {
 64          v=G[u][i];
 65          if(!visit[v]&&dy[v]==dx[u]+1)
 66          {
 67               visit[v]=true;
 68               if(!cy[v]||dfs(cy[v]))
 69               {
 70                   cy[v]=u;
 71                   cx[u]=v;
 72                   return true;
 73               }
 74          }
 75      }
 76      return false;
 77 }
 78 
 79 int Maxmatch()
 80 {
 81     memset(cx,0,sizeof(cx));
 82     memset(cy,0,sizeof(cy));
 83     int ans=0;
 84     while(search())
 85     {
 86         memset(visit,0,sizeof(visit));
 87         for(int i=1;i<=m;i++)
 88          if(!cx[i]&&dfs(i))
 89            ans++;
 90     }
 91    return ans;
 92 }
 93 int main()
 94 {
 95     int t,cnt=1;
 96     scanf("%d",&t);
 97     while(t--)
 98     {
 99        int tm;
100        int i,j;
101        scanf("%d",&tm);
102        scanf("%d",&m);
103        for(i=1;i<=m;i++)
104         scanf("%d %d %d",&X[i].x,&X[i].y,&speed[i]);
105        scanf("%d",&n);
106        for(i=1;i<=n;i++)
107         scanf("%d %d",&Y[i].x,&Y[i].y);
108        for(i=1;i<=m;i++)
109         {
110             G[i].clear();
111             for(j=1;j<=n;j++)
112              if(speed[i]*tm>=dis(i,j))
113                G[i].push_back(j);
114         }
115        printf("Scenario #%d:
",cnt++);
116        printf("%d

",Maxmatch());
117     }
118 
119     return 0;
120 }
View Code

 HDU 1054 Strategic Game

  最小点集覆盖 = 最大匹配

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        1505
 31 #define MAXM        MAXN*MAXN
 32 #define MODN        1000000007
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35  
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m;
 43 int vis[MAXN], link[MAXN];
 44 
 45 void init()
 46 {
 47     NE = 0;
 48     memset(head, -1, sizeof(head));
 49     memset(link, -1, sizeof(link));
 50 }
 51 
 52 void add_edge(int u, int v)
 53 {
 54     E[NE].v = v;
 55     E[NE].next = head[u];
 56     head[u] = NE++;
 57 }
 58 
 59 int dfs(int u)
 60 {
 61     for(int i = head[u]; i != -1; i = E[i].next)
 62     {
 63         int v = E[i].v;
 64         if(!vis[v])
 65         {
 66             vis[v] = 1;
 67             if(link[v] == -1 || dfs(link[v]))
 68             {
 69                 link[v] = u;
 70                 return 1;
 71             }
 72         }
 73     }
 74     return 0;
 75 }
 76 int solve()
 77 {
 78     int ans = 0;
 79     rep(i,0,n-1)
 80     {
 81         clr(vis);
 82         ans += dfs(i);
 83     }
 84     return ans;
 85 }
 86 
 87 int main()
 88 {
 89     int a, b;
 90     while(scanf("%d", &n) != EOF)
 91     {
 92         init();
 93         rep(i,0,n-1)
 94         {
 95             scanf("%d:(%d)", &a, &m);
 96             rep(j,0,m-1)
 97             {
 98                 scanf("%d", &b);
 99                 add_edge(a, b);
100                 add_edge(b, a);
101             }
102         }
103         printf("%d
", solve()/2);
104     }
105     return 0;
106 }
View Code

HDU 2819 Swap

  第一感觉应该是只通过行或者列就可以进行求解,如果既要考虑交换行也考虑交换列的情况,就会卷进死胡同。

  我选择行交换,首先进行一次二分图匹配,看是否每一列能够得到匹配,只要有一列没有得到匹配,那么就输出-1。否则处理得到的每一对匹配,行交换之后,相应的link值也要交换。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        105
 31 #define MAXM        MAXN*MAXN
 32 #define MODN        1000000007
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35  
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m;
 43 int vis[MAXN], link[MAXN];
 44 int a[MAXN], b[MAXN];
 45 
 46 void init()
 47 {
 48     NE = 0;
 49     memset(head, -1, sizeof(head));
 50     memset(link, -1, sizeof(link));
 51 }
 52 
 53 void add_edge(int u, int v)
 54 {
 55     E[NE].v = v;
 56     E[NE].next = head[u];
 57     head[u] = NE++;
 58 }
 59 
 60 int dfs(int u)
 61 {
 62     for(int i = head[u]; i != -1; i = E[i].next)
 63     {
 64         int v = E[i].v;
 65         if(!vis[v])
 66         {
 67             vis[v] = 1;
 68             if(link[v] == -1 || dfs(link[v]))
 69             {
 70                 link[v] = u;
 71                 return 1;
 72             }
 73         }
 74     }
 75     return 0;
 76 }
 77 int solve()
 78 {
 79     int ans = 0;
 80     rep(i,1,n)
 81     {
 82         clr(vis);
 83         if(!dfs(i))
 84             return -1;
 85         ans++;
 86     }
 87     return ans;
 88 }
 89 
 90 int main()
 91 {
 92     int t;
 93     while(scanf("%d", &n) != EOF)
 94     {
 95         init();
 96         rep(i,1,n)
 97         {
 98             rep(j,1,n)
 99             {
100                 scanf("%d", &t);
101                 if(t) add_edge(i, j);
102             }
103         }
104         int ans = solve();
105         if(ans == -1)
106         {
107             printf("-1
");
108             continue;  
109         } 
110         int cnt = 0;
111         rep(i,1,n)
112         {
113             if(link[i] == i) continue;
114             int j;
115             for(j = i+1; j <= n; j++)
116                 if(link[j] == i)
117                     break;
118             cnt++;
119             a[cnt] = i, b[cnt] = j;
120             swap(link[i], link[j]);
121         }
122         printf("%d
", cnt);
123         rep(i,1,cnt)
124             printf("C %d %d
", a[i], b[i]);
125     }
126     return 0;
127 }
View Code

【二分图多重匹配】 :与一般的最大匹配不同,二分图多重匹配中,每一个左节点有一个上限容量,可以匹配多个右节点。

 HDU 1669 Jamie's Contact Groups

  二分+二分图多重匹配。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        1005
 31 #define MAXM        MAXN*MAXN
 32 #define MODN        1000000007
 33 #define debug       puts("reach here");
 34 typedef long long LL;
 35  
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m;
 43 int vis[MAXN], link[505][MAXN];
 44 int cnt[MAXN];
 45 int cap;
 46 
 47 void init()
 48 {
 49     NE = 0;
 50     memset(head, -1, sizeof(head));
 51 }
 52 
 53 void add_edge(int u, int v)
 54 {
 55     E[NE].v = v;
 56     E[NE].next = head[u];
 57     head[u] = NE++;
 58 }
 59 
 60 int dfs(int u)
 61 {
 62     for(int i = head[u]; i != -1; i = E[i].next)
 63     {
 64         int v = E[i].v;
 65         if(!vis[v])
 66         {
 67             vis[v] = 1;
 68             if(cnt[v] < cap)
 69             {
 70                 link[v][cnt[v]++] = u;
 71                 return true;
 72             }
 73             rep(j,0,cnt[v]-1)
 74             {
 75                 if(dfs(link[v][j]))
 76                 {
 77                     link[v][j] = u;
 78                     return true;
 79                 }
 80             }
 81         }
 82     }
 83     return 0;
 84 }
 85 bool solve()
 86 {
 87     clr(cnt);
 88     memset(link, -1, sizeof(link));
 89     rep(i,1,n)
 90     {
 91         clr(vis);
 92         if(!dfs(i))
 93             return false;
 94     }
 95     return true;
 96 }
 97 
 98 int main()
 99 {
100     char s[20];
101     int a;
102     while(scanf("%d%d", &n, &m) != EOF)
103     {
104         if(n == 0 && m == 0)
105             break;
106         init();
107         rep(i,1,n)
108         {
109             scanf("%s", s);
110             while(getchar() == ' ')
111             {
112                 scanf("%d", &a);
113                 add_edge(i, a);
114             }
115         }
116         int l = 0, r = MAXN;
117         while(l <= r)
118         {
119             cap = (l + r) >> 1;
120             if(solve())
121                 r = cap-1;
122             else
123                 l = cap+1;
124         }
125         printf("%d
", l);
126     }
127     return 0;
128 }
View Code

HDU 3605 Escape

  裸的二分图多重匹配,不提。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        100005
 31 #define MAXM        4000005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35 
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m, k;
 43 bool vis[20];
 44 int link[20][MAXN];
 45 int cnt[MAXN], cap[MAXN];
 46 
 47 void init()
 48 {
 49     NE = 0;
 50     clr(cnt);
 51     memset(head, -1, sizeof head);
 52     memset(link, -1, sizeof link);
 53 }
 54 
 55 void add_edge(int u, int v)
 56 {
 57     E[NE].v = v;
 58     E[NE].next = head[u];
 59     head[u] = NE++;
 60 }
 61 
 62 int dfs(int u)
 63 {
 64     for(int i = head[u]; i != -1; i = E[i].next)
 65     {
 66         int v = E[i].v;
 67         if(!vis[v])
 68         {
 69             vis[v] = 1;
 70             if(cnt[v] < cap[v])
 71             {
 72                 link[v][cnt[v]] = u;
 73                 cnt[v]++;
 74                 return 1;
 75             }
 76             rep(j,0,cnt[v]-1)
 77             {
 78                 if(dfs(link[v][j]))
 79                 {
 80                     link[v][j] = u;
 81                     return 1;
 82                 }
 83             }
 84         }
 85     }
 86     return 0;
 87 }
 88 
 89 bool solve()
 90 {
 91     rep(i,1,n)
 92     {
 93         clr(vis);
 94         if(!dfs(i))
 95             return false;
 96     }
 97     return true;
 98 }
 99 
100 
101 int main()
102 {
103     int a;
104     while(scanf("%d%d", &n, &m) != EOF)
105     {
106         init();
107         rep(i,1,n) rep(j,1,m)
108         {
109             scanf("%d", &a);
110             if(a) add_edge(i, j);
111         }
112         rep(i,1,m)
113             scanf("%d", &cap[i]);
114         printf("%s
", solve() ? "YES" : "NO");
115     }
116     return 0;
117 }
View Code

HDU 3861 The King’s Problem

  由题意可知,如果两个城市同属一个强连通分量必须同属一个州,先用Tarjan进行求出强连通分量,缩点后求二分图的最小路径覆盖。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <algorithm>
  9 #include <sstream>
 10 #include <iostream>
 11 #include <iomanip>
 12 #include <cstdio>
 13 #include <cstdlib>
 14 #include <cstring>
 15 #include <queue>
 16 using namespace std;
 17 #define pii         pair<int,int>
 18 #define clr(a)      memset((a),0,sizeof (a))
 19 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 20 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 21 #define inf         (0x3f3f3f3f)
 22 #define eps         1e-6
 23 #define MAXN        5005
 24 #define MAXM        100005
 25 #define MODN        1000000007
 26 #define debug       puts("reach here");
 27 typedef long long LL;
 28 
 29 struct Node
 30 {
 31     int v, next;
 32 }E[MAXM], E1[MAXM];
 33 
 34 int NE, head[MAXN], NE1, head1[MAXN];
 35 bool vis[MAXN];
 36 int link[MAXN];
 37 int n, m;
 38 int dfn[MAXN], stk[MAXN], low[MAXN], col[MAXN], ins[MAXN], cols, top, ind, tmp;
 39 
 40 void add_edge(int u, int v)
 41 {
 42     E[NE].v = v;
 43     E[NE].next = head[u];
 44     head[u] = NE++;
 45 }
 46 
 47 void add_edge1(int u, int v)
 48 {
 49     E1[NE1].v = v;
 50     E1[NE1].next = head1[u];
 51     head1[u] = NE1++;
 52 }
 53 
 54 void init()
 55 {
 56     NE = NE1 = 0;
 57     memset(head, -1, sizeof head);
 58     memset(head1, -1, sizeof head1);
 59 }
 60 
 61 int dfs(int u)
 62 {
 63     for(int i = head1[u]; i != -1; i = E1[i].next)
 64     {
 65         int v = E1[i].v;
 66         if(!vis[v])
 67         {
 68             vis[v] = 1;
 69             if(link[v] == -1 || dfs(link[v]))
 70             {
 71                 link[v] = u;
 72                 return 1;
 73             }
 74         }
 75     }
 76     return 0;
 77 }
 78 
 79 int solve()
 80 {
 81     int ans = 0;
 82     memset(link, -1, sizeof link);
 83     rep(i,1,cols)
 84     {
 85         clr(vis);
 86         ans += dfs(i);
 87     }
 88     return ans;
 89 }
 90 
 91 void dfs1(int u)
 92 {
 93     dfn[u] = low[u] = ++ind;
 94     stk[++top] = u;
 95     ins[u] = 1;
 96     for(int i = head[u]; i != -1; i = E[i].next)
 97     {
 98         int v = E[i].v;
 99         if(!dfn[v])
100         {
101             dfs1(v);
102             low[u] = min(low[u], low[v]);
103         }
104         else if(ins[v])
105             low[u] = min(low[u], dfn[v]);
106     }
107     if(dfn[u] == low[u])
108     {
109         cols++;
110         do
111         {
112             tmp = stk[top--];
113             col[tmp] = cols;
114             ins[tmp] = 0;
115         }while(tmp != u);
116     }
117 }
118 
119 void tarjan()
120 {
121     clr(dfn); clr(low);
122     clr(ins); clr(col);
123     clr(stk);
124     top = cols = ind = 0;
125     rep(i,1,n)
126         if(!dfn[i])
127             dfs1(i);
128     for(int u = 1; u <= n; u++)
129     {
130         for(int i = head[u]; i != -1; i = E[i].next)
131         {
132             int v = E[i].v;
133             if(col[u] == col[v]) continue;
134             add_edge1(col[u], col[v]);
135         }
136     }
137     printf("%d
", cols - solve());
138 }
139 
140 int main()
141 {
142     int t, a, b;
143     scanf("%d", &t);
144     while(t--)
145     {
146         scanf("%d%d", &n, &m);
147         init();
148         rep(i,1,m)
149         {
150             scanf("%d%d", &a, &b);
151             add_edge(a, b);
152         }
153         tarjan();
154     }
155     return 0;
156 }
View Code

HDU 2236 无题II

  二分差值,然后暴力枚举最大最小值+匈牙利判断二分图满匹配。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <algorithm>
  9 #include <sstream>
 10 #include <iostream>
 11 #include <iomanip>
 12 #include <cstdio>
 13 #include <cstdlib>
 14 #include <cstring>
 15 #include <queue>
 16 using namespace std;
 17 #define pii         pair<int,int>
 18 #define clr(a)      memset((a),0,sizeof (a))
 19 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 20 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 21 #define inf         (0x3f3f3f3f)
 22 #define eps         1e-6
 23 #define MAXN        105
 24 #define MAXM        100005
 25 #define MODN        1000000007
 26 #define debug       puts("reach here")
 27 #define MP          make_pair
 28 #define PB          push_back
 29 #define RI(x)       scanf("%d",&x)
 30 #define RII(x,y)    scanf("%d%d",&x,&y)
 31 #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
 32 typedef long long LL;
 33 
 34 bool vis[MAXN];
 35 int link[MAXN];
 36 int g[MAXN][MAXN];
 37 int n, m, s, t;
 38 int low, mid;
 39 
 40 int dfs(int u)
 41 {
 42     rep(v,1,n)
 43     {
 44         if(!vis[v] && (g[u][v] >= low && g[u][v] <= low + mid))
 45         {
 46             vis[v] = 1;
 47             if(link[v] == -1 || dfs(link[v]))
 48             {
 49                 link[v] = u;
 50                 return 1;
 51             }
 52         }
 53     }
 54     return 0;
 55 }
 56 
 57 int solve()
 58 {
 59     memset(link, -1, sizeof link);
 60     rep(i,1,n)
 61     {
 62         clr(vis);
 63         if(!dfs(i))
 64             return 0;
 65     }
 66     return 1;
 67 }
 68 
 69 int check()
 70 {
 71     for(low = s; low + mid <= t; low++)
 72         if(solve())
 73             return true;
 74     return false;
 75 }
 76 
 77 int main()
 78 {
 79     int cas;
 80     scanf("%d", &cas);
 81     while(cas--)
 82     {
 83         scanf("%d", &n);
 84         s = inf, t = -1;
 85         rep(i,1,n)
 86         {
 87             rep(j,1,n)
 88             {
 89                 scanf("%d", &g[i][j]);
 90                 s = min(s, g[i][j]);
 91                 t = max(t, g[i][j]);
 92             }
 93         }
 94         int l = 0, r = t-s;
 95         while(l <= r)
 96         {
 97             mid = (l + r) >> 1;
 98             if(check())
 99                 r = mid - 1;
100             else
101                 l = mid + 1;
102         }
103         printf("%d
", l);
104     }
105     return 0;
106 }
View Code

 HDU 2458 Kindergarten

  逆向建图,对于没有成为好朋友的男生女生之间连一条边,那么答案为“G+B-最大匹配”。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        100005
 31 #define MAXM        4000005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35 
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN];
 42 int n, m, k;
 43 bool vis[MAXN];
 44 int link[MAXN];
 45 bool g[205][205];
 46 
 47 void init()
 48 {
 49     NE = 0;
 50     memset(head, -1, sizeof head);
 51     memset(link, -1, sizeof link);
 52 }
 53 
 54 void add_edge(int u, int v)
 55 {
 56     E[NE].v = v;
 57     E[NE].next = head[u];
 58     head[u] = NE++;
 59 }
 60 
 61 int dfs(int u)
 62 {
 63     for(int i = head[u]; i != -1; i = E[i].next)
 64     {
 65         int v = E[i].v;
 66         if(!vis[v])
 67         {
 68             vis[v] = 1;
 69             if(link[v] == -1 || dfs(link[v]))
 70             {
 71                 link[v] = u;
 72                 return 1;
 73             }
 74         }
 75     }
 76     return 0;
 77 }
 78 
 79 int solve()
 80 {
 81     int ans = 0;
 82     rep(i,1,n)
 83     {
 84         clr(vis);
 85         ans += dfs(i);
 86     }
 87     return ans;
 88 }
 89 
 90 
 91 int main()
 92 {
 93     int a, b, cas = 1;
 94     while(scanf("%d%d%d", &n, &m, &k) != EOF)
 95     {
 96         if(n==0 && m==0 && k==0) break;
 97         clr(g);
 98         rep(i,1,k)
 99         {
100             scanf("%d%d", &a, &b);
101             g[a][b] = true;
102         }
103         init();
104         rep(i,1,n)
105             rep(j,1,m)
106                 if(!g[i][j])
107                     add_edge(i, j);
108         printf("Case %d: %d
", cas++, n+m-solve());
109     }
110     return 0;
111 }
View Code

HDU 4185 Oil Skimming

  对于能构成一个小长方形的两个格子建一条边表示这样是一个合法的匹配,建好二分图后求最大匹配就是了。

  1 #include <vector>
  2 #include <list>
  3 #include <map>
  4 #include <set>
  5 #include <queue>
  6 #include <deque>
  7 #include <stack>
  8 #include <bitset>
  9 #include <algorithm>
 10 #include <functional>
 11 #include <numeric>
 12 #include <utility>
 13 #include <sstream>
 14 #include <iostream>
 15 #include <iomanip>
 16 #include <cstdio>
 17 #include <cmath>
 18 #include <cstdlib>
 19 #include <cstring>
 20 #include <ctime>
 21 #include <queue>
 22 #include <cassert>
 23 using namespace std;
 24 #define pii         pair<int,int>
 25 #define clr(a)      memset((a),0,sizeof (a))
 26 #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
 27 #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
 28 #define inf         (0x3f3f3f3f)
 29 #define eps         1e-6
 30 #define MAXN        605
 31 #define MAXM        4000005
 32 #define MODN        (1000000007)
 33 #define test        puts("reach here");
 34 typedef long long LL;
 35 
 36 struct Node
 37 {
 38     int v, next;
 39 }E[MAXM];
 40 
 41 int NE, head[MAXN*MAXN];
 42 int n, m, k;
 43 bool vis[MAXN*MAXN];
 44 int link[MAXN*MAXN];
 45 char g[MAXN][MAXN];
 46 
 47 void init()
 48 {
 49     NE = 0;
 50     memset(head, -1, sizeof head);
 51     memset(link, -1, sizeof link);
 52 }
 53 
 54 void add_edge(int u, int v)
 55 {
 56     E[NE].v = v;
 57     E[NE].next = head[u];
 58     head[u] = NE++;
 59 }
 60 
 61 int dfs(int u)
 62 {
 63     for(int i = head[u]; i != -1; i = E[i].next)
 64     {
 65         int v = E[i].v;
 66         if(!vis[v])
 67         {
 68             vis[v] = 1;
 69             if(link[v] == -1 || dfs(link[v]))
 70             {
 71                 link[v] = u;
 72                 return 1;
 73             }
 74         }
 75     }
 76     return 0;
 77 }
 78 
 79 int solve()
 80 {
 81     int ans = 0;
 82     rep(i,0,n*n-1)
 83     {
 84         clr(vis);
 85         ans += dfs(i);
 86     }
 87     return ans;
 88 }
 89 
 90 
 91 int main()
 92 {
 93     int t, cas = 1;
 94     scanf("%d", &t);
 95     while(t--)
 96     {
 97         scanf("%d", &n);
 98         rep(i,0,n-1)
 99             scanf("%s", g[i]);
100         init();
101         rep(i,0,n-1)
102         {
103             rep(j,0,n-1)
104             {
105                 if(g[i][j] == '.') continue;
106                 int x = j+1, y = i;
107                 if(x < n && g[y][x] != '.')
108                 {
109                     add_edge(j + i*n, x + y*n);
110                     add_edge(x + y*n, j + i*n);
111                 }
112                 x = j, y = i+1;
113                 if(y < n && g[y][x] != '.')
114                 {
115                     add_edge(j + i*n, x + y*n);
116                     add_edge(x + y*n, j + i*n);
117                 }   
118             }
119         }
120         printf("Case %d: %d
", cas++, solve()/2);
121     }
122     return 0;
123 }
View Code
原文地址:https://www.cnblogs.com/huangfeihome/p/3364411.html