一个矩阵里放着一些目标,打一枪可以打掉一行、一列,问最少打多少枪。
row、col集合放着点,row中的一个点row-i连向col中的一个点col-j,代表(i,j)放着一个目标。
这样选最小的点覆盖所有的边就可以了
最小点覆盖==最大匹配
1 // poj 3041 2 3 #include<iostream> 4 #include<set> 5 #include<map> 6 #include<vector> 7 using namespace std; 8 int path(int row, vector<set<int> >& rowToCol, vector<int>& matchColToRow, set<int>& visited){ 9 for(set<int>::iterator it = rowToCol[row].begin(); it != rowToCol[row].end(); it++){ 10 int col = *it; 11 if(visited.find(*it) != visited.end()) continue; 12 visited.insert(*it); 13 if(matchColToRow[col] == 0 || path(matchColToRow[col], rowToCol, matchColToRow, visited)){ 14 matchColToRow[col] = row; 15 return 1; 16 } 17 } 18 return 0; 19 } 20 21 int main(){ 22 int n, k; 23 cin>>n>>k; 24 vector<set<int> > rowToCol(n + 1); // rowToCol[i]表示第 i row喜欢哪些col // row等于奶牛 // col等于stall 25 vector<int> matchColToRow(n + 1, 0); 26 for(int i = 0; i < k; i++){ 27 int x, y; 28 cin>>x>>y; 29 rowToCol[x].insert(y); 30 } 31 int ans = 0; 32 for(int row = 1; row <= n; row++){ 33 set<int> visited; 34 ans += path(row, rowToCol, matchColToRow, visited); 35 } 36 cout<<ans; 37 return 0; 38 }