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 }
> 别忘了 总有人在等着你