poj1422 Air Raid

传送门

读题读了半天...还读错了一次写了个拓扑排序写跪了......

题意就是给一个有向图

伞兵降临在城镇的一个交叉口(node)并可以沿着街道(edge)走向另一个没有被其他伞兵走过的交叉口

保证无环

所以是个最小点覆盖

由于最大匹配+最小点覆盖 = 点数

所以跑一边匹配就OK

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define ms(a,b) memset(a,b,sizeof a)
 6 #define rep(i,a,n) for(int i = a;i <= n;++i)
 7 #define per(i,n,a) for(int i = n;i >= a;--i)
 8 #define inf 2147483647
 9 #define eps 1e-9
10 using namespace std;
11 typedef long long ll;
12 ll read() {
13     ll as = 0,fu = 1;
14     char c = getchar();
15     while(c < '0' || c > '9') {
16     if(c == '-') fu = -1;
17     c = getchar();
18     }
19     while(c >= '0' && c <= '9') {
20     as = as * 10 + c - '0';
21     c = getchar();
22     }
23     return as * fu;
24 }
25 //head
26 const int N = 100006;
27 int n,m,ans;
28 int head[N],mo[N],nxt[N],cnt;
29 void add(int x,int y) {
30     mo[++cnt] = y;
31     nxt[cnt] = head[x];
32     head[x] = cnt;
33 }
34 
35 int match[N],vis[N];
36 bool dfs(int x,int tm) {
37     for(int i = head[x];i;i = nxt[i]) {
38     int sn = mo[i];
39     if(vis[sn] == tm) continue;
40     vis[sn] = tm;
41     if(!match[sn] || dfs(match[sn],tm)) {
42         match[sn] = x;
43         return 1;
44     }
45     }
46     return 0;
47 }
48 
49 void solve() {
50     ms(match,0),ms(vis,0),ms(head,0);
51     n = read(),m = read(),ans = 0;
52     rep(i,1,m) {
53     int x = read(),y = read();
54     add(x,y);
55     }
56     rep(i,1,n) ans += dfs(i,i);
57     printf("%d\n",n - ans);
58 }
59 
60 int main() {
61     int T = read();
62     while(T--) solve();
63     return 0;
64 }
View Code

 

posted @ 2018-10-18 17:05  白怀潇  阅读(173)  评论(0编辑  收藏  举报