1. 程式人生 > >UVa 11419 我是SAM(最小點覆蓋+路徑輸出)

UVa 11419 我是SAM(最小點覆蓋+路徑輸出)

二分圖 現在 over div space void net https 最小點覆蓋

https://vjudge.net/problem/UVA-11419

題意:一個網格裏面有一些目標,可以從某一行,某一列發射一發子彈,可以打掉它;求最少的子彈,和在哪裏打?

思路:

每個點的x坐標與y坐標相連,現在就是要找一個最小點覆蓋,同時還要輸出哪些點被覆蓋了。

 1 #include <cstdio>  
 2 #include <cstring>  
 3 #include <vector>  
 4 #include <algorithm>  
 5 using namespace std;  
 6   
 7
const int maxn = 1000 + 5; // 單側頂點的最大數目 8 9 // 二分圖最大基數匹配 10 struct BPM { 11 int n, m; // 左右頂點個數 12 vector<int> G[maxn]; // 鄰接表 13 int left[maxn]; // left[i]為右邊第i個點的匹配點編號,-1表示不存在 14 bool T[maxn]; // T[i]為右邊第i個點是否已標記 15 16 int right[maxn]; //
求最小覆蓋用 17 bool S[maxn]; // 求最小覆蓋用 18 19 void init(int n, int m) { 20 this->n = n; 21 this->m = m; 22 for(int i = 0; i < n; i++) G[i].clear(); 23 } 24 25 void AddEdge(int u, int v) { 26 G[u].push_back(v); 27 } 28 29 bool
match(int u){ 30 S[u] = true; 31 for(int i = 0; i < G[u].size(); i++) { 32 int v = G[u][i]; 33 if (!T[v]){ 34 T[v] = true; 35 if (left[v] == -1 || match(left[v])){ 36 left[v] = u; 37 right[u] = v; 38 return true; 39 } 40 } 41 } 42 return false; 43 } 44 45 // 求最大匹配 46 int solve() { 47 memset(left, -1, sizeof(left)); 48 memset(right, -1, sizeof(right)); 49 int ans = 0; 50 for(int u = 0; u < n; u++) { // 從左邊結點u開始增廣 51 memset(S, 0, sizeof(S)); 52 memset(T, 0, sizeof(T)); 53 if(match(u)) ans++; 54 } 55 return ans; 56 } 57 58 // 求最小覆蓋。X和Y為最小覆蓋中的點集 59 int mincover(vector<int>& X, vector<int>& Y) { 60 int ans = solve(); 61 memset(S, 0, sizeof(S)); 62 memset(T, 0, sizeof(T)); 63 for(int u = 0; u < n; u++) 64 if(right[u] == -1) match(u); // 從所有X未蓋點出發增廣 65 for(int u = 0; u < n; u++) 66 if(!S[u]) X.push_back(u); // X中的未標記點 67 for(int v = 0; v < m; v++) 68 if(T[v]) Y.push_back(v); // Y中的已標記點 69 return ans; 70 } 71 }; 72 73 BPM solver; 74 75 int R, C, N; 76 77 int main(){ 78 int kase = 0; 79 while(scanf("%d%d%d", &R, &C, &N) == 3 && R && C && N) { 80 solver.init(R, C); 81 for(int i = 0; i < N; i++) { 82 int r, c; 83 scanf("%d%d", &r, &c); r--; c--; 84 solver.AddEdge(r, c); 85 } 86 vector<int> X, Y; 87 int ans = solver.mincover(X, Y);//把結果放在X,Y裏面 88 printf("%d", ans); 89 for(int i = 0; i < X.size(); i++) printf(" r%d", X[i]+1); 90 for(int i = 0; i < Y.size(); i++) printf(" c%d", Y[i]+1); 91 printf("\n"); 92 } 93 return 0; 94 }

UVa 11419 我是SAM(最小點覆蓋+路徑輸出)