标签:
原题连接:http://poj.org/problem?id=3041
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 17985 | Accepted: 9798 |
Description
Input
Output
Sample Input
3 4 1 1 1 3 2 2 3 2
Sample Output
2
Hint
Source
给你一个$N*N$的棋盘,其中某些地方有棋子,你可以每次消除一列或者一行,问你至少需要多少次操作,把棋子消除完。
这是一道二分匹配的经典问题。将每个棋子的横纵坐标连边,那么就会构成一个二分图,问题就转化为求解这个二分图的最小点覆盖。由最小点覆盖就是最大匹配,跑一发dinic就好。
#include<iostream> #include<stack> #include<vector> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<cstdio> #include<queue> #define MAX_S (1<<10)+10 #define MAX_V 1234 #define MAX_N MAX_V #define INF 1000009 using namespace std; struct edge { int to, cap, rev; bool isRev; edge(int t, int c, int r, bool i) : to(t), cap(c), rev(r), isRev(i) { } edge() { } }; template <class T> inline bool scan_d(T &ret) { char c; int sgn; if(c=getchar(),c==EOF) return 0; //EOF while(c!=‘ -‘ &&(c<‘0‘ ||c>‘9‘ )) c=getchar(); sgn=(c==‘ -‘ )?-1:1; ret=(c==‘ -‘ )?0:(c-‘0‘ ); while(c=getchar(),c>=‘0‘ &&c<=‘9‘ ) ret=ret*10+(c-‘0‘ ); ret*=sgn; return 1; } vector<edge> G[MAX_N]; int level[MAX_V]; int iter[MAX_V]; void init(int totNode) { for (int i = 0; i <= totNode; i++) G[i].clear(); memset(level, 0, sizeof(level)); memset(iter, 0, sizeof(iter)); } void add_edge(int from,int to,int cap) { G[from].push_back(edge (to, cap, G[to].size(),0)); G[to].push_back(edge (from, 0, G[from].size() - 1,1)); } void bfs(int s) { queue<int> que; memset(level, -1, sizeof(level)); level[s] = 0; que.push(s); while (!que.empty()) { int v = que.front(); que.pop(); for (int i = 0; i < G[v].size(); i++) { edge &e = G[v][i]; if (e.cap > 0 && level[e.to] < 0) { level[e.to] = level[v] + 1; que.push(e.to); } } } } int dfs(int v,int t,int f) { if (v == t)return f; for (int &i = iter[v]; i < G[v].size(); i++) { edge &e = G[v][i]; if (e.cap > 0 && level[v] < level[e.to]) { int d = dfs(e.to, t, min(f, e.cap)); if (d > 0) { e.cap -= d; G[e.to][e.rev].cap += d; return d; } } } return 0; } int max_flow(int s,int t) { int flow = 0; for (; ;) { bfs(s); if (level[t] < 0)return flow; memset(iter, 0, sizeof(iter)); int f; while ((f = dfs(s, t, INF)) > 0) { flow += f; } } } int n,m; int S=1233,T=1212; int main() { cin.sync_with_stdio(false); cin >> n >> m; for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; add_edge(u, v+n, 1); } for (int i = 1; i <= n; i++) { add_edge(S, i, 1); add_edge(i+n, T, 1); } cout << max_flow(S, T) << endl; return 0; }
标签:
原文地址:http://www.cnblogs.com/HarryGuo2012/p/4811750.html