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

本文介绍了一种使用网络流解决二分图最大匹配问题的方法,通过构造特定的图结构并运用Dinic算法求解最大流,最终获得男女间最佳匹配方案。需要注意男女编号及边的方向。

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

 

转载于:https://www.cnblogs.com/Newdawn/p/4674683.html

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值