hdu 2063 过山车(二分图最佳匹配)

  经典的二分图最大匹配问题,因为匈牙利算法我还没有认真去看过,想先试试下网络流的做法,即对所有女生增加一个超级源,对所有男生增加一个超级汇,然后按照题意的匹配由女生向男生连一条边,跑一个最大流就是答案(以上所有边容量均为 1 ),我是直接上 Dinic 算法的模板的:

  1 #include<cstdio>

  2 #include<cstring>

  3 #include<vector>

  4 #include<queue>

  5 #include<algorithm>

  6 using namespace std;

  7 #define  sd(x)  scanf("%d",&(x))

  8 const int inf = 0x3fffffff;

  9 

 10 struct Edge {

 11     int from, to, cap, flow;

 12     Edge() {}

 13     Edge(int from, int to, int cap, int flow):

 14         from(from), to(to), cap(cap), flow(flow) {}

 15 };

 16 

 17 const int N = 1003;

 18 

 19 struct Dinic {

 20     int s,t;

 21     vector<Edge> edges;

 22     vector<int> G[N];

 23     bool vis[N];

 24     int d[N];

 25     int cur[N];

 26 

 27     void clear() {

 28         edges.clear();

 29         for(int i = 0; i < N; ++i)

 30             G[i].clear();

 31     }

 32     void addEdge(int from, int to, int cap) {

 33         edges.push_back(Edge(from, to, cap, 0));

 34         edges.push_back(Edge(to, from, 0, 0));

 35         int m = edges.size();

 36         G[from].push_back(m - 2);

 37         G[to].push_back(m - 1);

 38     }

 39     bool bfs() {

 40         memset(vis,0,sizeof(vis));

 41         queue<int> q;

 42         q.push(s);

 43         d[s] = 0;

 44         vis[s] = 1;

 45         while(!q.empty()) {

 46             int x = q.front();  q.pop();

 47             int len = G[x].size();

 48             for(int i = 0; i < len; ++i) {

 49                 Edge &e = edges[G[x][i]];

 50                 if(!vis[e.to] && e.cap > e.flow) {

 51                     d[e.to] = d[x] + 1;

 52                     vis[e.to] = 1;

 53                     q.push(e.to);

 54                 }

 55             }

 56         }

 57         return vis[t];

 58     }

 59     int dfsAll(int x, int a) {

 60         if(x == t || a == 0)    return a;

 61         int flow = 0, f, len = G[x].size();

 62         for(int &i = cur[x]; i < len; ++i) {

 63             Edge &e = edges[G[x][i]];

 64             if(d[e.to] == d[x] + 1 && (f = dfsAll(e.to, min(a, e.cap - e.flow)) > 0)) {

 65                 e.flow += f;

 66                 edges[G[x][i]^ 1].flow -= f;

 67                 flow += f;

 68                 a -= f;

 69                 if(a == 0)  break;

 70             }

 71         }

 72         return flow;

 73     }

 74     int Maxflow(int s, int t) {

 75         this->s = s;

 76         this->t = t;

 77         int flow = 0;

 78         while(bfs()) {

 79             memset(cur, 0, sizeof(cur));

 80             flow += dfsAll(s,inf);

 81         }

 82         return flow;

 83     }

 84 } dinic;

 85 

 86 int c[1003];

 87 

 88 #define sd2(x,y)  scanf("%d%d",&(x),&(y))

 89 #define sd3(x,y,z)  scanf("%d%d%d",&(x),&(y),&(z))

 90 

 91 int main() {

 92     int n,m,k,x,y;

 93     while(~sd3(k, m, n), k) {

 94         dinic.clear();

 95         while(k--) {

 96             sd2(x,y);

 97             y += m;

 98             dinic.addEdge(x, y, 1);

 99 //            dinic.addEdge(y, x, 1);

100         }

101         for(int i = 1; i <= m; ++i)

102             dinic.addEdge(0, i, 1);

103         for(int i = m + 1; i <= m + n; ++i)

104             dinic.addEdge(i, m + n + 1, 1);

105         printf("%d\n",dinic.Maxflow(0, m + n + 1));

106     }

107     return 0;

108 }
最大流实现最佳匹配

  需要注意的是男女生的编号,还有女生指向男生的是有向边,不需要两次的 addEdge。wa 了两次才找出所有问题。。。

 

你可能感兴趣的:(HDU)