码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-07-24 22:35:15      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:

  经典的二分图最大匹配问题,因为匈牙利算法我还没有认真去看过,想先试试下网络流的做法,即对所有女生增加一个超级源,对所有男生增加一个超级汇,然后按照题意的匹配由女生向男生连一条边,跑一个最大流就是答案(以上所有边容量均为 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 2063 过山车(二分图最佳匹配)

标签:

原文地址:http://www.cnblogs.com/Newdawn/p/4674683.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!