KM算法模板
来源:互联网 发布:个股龙虎榜数据 编辑:程序博客网 时间:2024/05/19 18:17
模板:
O(n^4)
const int maxn=1005;const int INF=1e9;bool sx[maxn], sy[maxn];int match[maxn],lx[maxn], ly[maxn];int n, m, d;int g[maxn][maxn];int sum;//n:左集元素个数; m:右集元素个数// g[i][j] 代表i到j的边权bool dfs (int u){ int v; sx[u] = true; for (v = 1; v <=m; v++) { if (!sy[v] && lx[u]+ly[v]==g[u][v]) { sy[v] = true; if (match[v] == -1 || dfs (match[v])) { match[v] = u; return true; } } } return false;}void KM (){ int i, j, k, ans = 0; memset (ly, 0, sizeof(ly)); for (i = 1; i <=n; i++) { lx[i] = -INF; for (j = 1; j <=m; j++) if (lx[i] < g[i][j]) lx[i] = g[i][j]; } memset (match, -1, sizeof(match)); for (i =1; i <=n; i++) { while (1) { memset (sx, false, sizeof(sx)); memset (sy, false, sizeof(sy)); if (dfs (i)) break; d = INF; for (j =1; j <=n; j++) if (sx[j]) for (k =1;k<=m; k++) if (!sy[k]) d = min (d,lx[j]+ly[k]-g[j][k]); for (j =1; j <=n; j++) if (sx[j]) lx[j] -= d; for (j =1; j <=m; j++) if (sy[j]) ly[j] += d; } } for (i = 1; i <= m; i++) if (match[i] !=-1&&g[match[i]][i]!=-INF) ans += g[match[i]][i]; printf("%d\n",ans);}
O(n^3)
const int maxn=1005;int g[maxn][maxn];bool visitx[maxn], visity[maxn];int lx[maxn], ly[maxn];int slack[maxn];int match[maxn];int n,m;bool Hungary(int u) //匈牙利算法{ visitx[u] = true; for(int i = 1; i <= n; ++i) { if(visity[i]) continue; if(lx[u] + ly[i] == g[u][i]) { visity[i] = true; if(match[i] == -1 || Hungary(match[i])) { match[i] = u; return true; } } else //不在相等子图 slack[i] = min(slack[i], lx[u] + ly[i] - g[u][i]); } return false;}void KM(){ int temp;memset(match, -1, sizeof(match)); memset(lx, 0, sizeof(lx)); //初始化顶标 memset(ly, 0, sizeof(ly)); //ly[i]为0 for(int i = 1; i <= n; ++i) //lx[i]为权值最大的边 for(int j = 0; j <= m; ++j) lx[i] = max(lx[i], g[i][j]); for(int i = 1; i <= n; i++) //对n个点匹配 { for(int j = 1; j <= n; j++) slack[j] = INT_MAX; while(1) { memset(visitx, false, sizeof(visitx)); memset(visity, false, sizeof(visity)); if(Hungary(i)) //匹配成功 break; else //匹配失败,找最小值 { temp = INT_MAX; for(int j = 1; j <= n; j++) if(!visity[j]) if(temp > slack[j]) temp = slack[j]; for(int j = 1; j <= n; j++) //更新顶标 { if(visitx[j]) lx[j] -= temp; } for(int j=1;j<=m;++j) { if(visity[j]) ly[j] += temp; else slack[j] -= temp; } } } }int ans = 0; for(int i = 1; i <= m; ++i) //权值相加 ans += g[match[i]][i]; printf("%d\n", ans);}
0 0
- KM算法模板
- KM算法 详解+模板
- KM算法详解+模板
- KM算法 详解+模板
- KM算法 详解+模板
- KM算法模板
- KM算法模板
- KM算法 详解+模板
- KM算法 详解+模板
- KM算法 详解+模板
- KM算法模板
- KM算法模板 hdu2255
- KM算法 详解+模板
- KM算法详解,模板
- KM算法模板
- KM算法模板
- KM算法模板(HDU_2255)
- KM算法模板
- SQL Server 2005 创建链接服务器
- iOS8自定义cell的删除按钮、更多、置顶等按钮的样式
- 黑马程序员-c语言基础自增自减问题
- 冒泡排序`交换排序·二分查找
- POJ 1141
- KM算法模板
- [150518]spring四种依赖注入方式
- 我的第一篇博客,仅做一些预言
- Ural 2018 The Debut Album
- git 的一些用法
- iOS开发 FFmpeg 编译及使用
- OLAP与OLTP
- c#lock语句及在单例模式中应用
- crontab Linux