HDU 3488 — Tour 费用流/KM算法
2015-05-29 22:32
288 查看
原题:http://acm.hdu.edu.cn/showproblem.php?pid=3488
题意:
有n个点,m条有向带权边;
求一些环,使得每个点属于且仅属于一个环;
问环边的权值和的最小值;
思路:
拆点,建图,跑一个费用流;
源点到节点,流量为1,花费为0(s, i, 0, 1);
节点到节点,流量为1, 花费为边权值(u, v+n, cos, 1);
节点到汇点,流量为1,花费为0(i+n, t, 0, 1);
题意:
有n个点,m条有向带权边;
求一些环,使得每个点属于且仅属于一个环;
问环边的权值和的最小值;
思路:
拆点,建图,跑一个费用流;
源点到节点,流量为1,花费为0(s, i, 0, 1);
节点到节点,流量为1, 花费为边权值(u, v+n, cos, 1);
节点到汇点,流量为1,花费为0(i+n, t, 0, 1);
#include <cstdio> #include <cstring> #include <queue> #include <vector> #define oo 0x3f3f3f3f #define maxn 410 using namespace std; struct Edge { int u, v, c, f; Edge( int u, int v, int c, int f ):u(u),v(v),c(c),f(f){} }; struct Mcmf { int n, src, dst; vector<Edge> edge; vector<int> g[maxn]; int dis[maxn], ext[maxn], pth[maxn]; void init( int nn, int s, int d ) { n = nn; src = s; dst = d; for( int i=1; i<=n; i++ ) g[i].clear(); edge.clear(); } void add_edge( int u, int v, int c, int f ) { g[u].push_back( edge.size() ); edge.push_back( Edge(u,v,c,f) ); g[v].push_back( edge.size() ); edge.push_back( Edge(v,u,-c,0) ); } bool spfa( int &flow, int &cost ) { queue<int> qu; memset( dis, 0x3f, sizeof(dis) ); qu.push( src ); dis[src] = 0; ext[src] = true; pth[src] = -1; while( !qu.empty() ) { int u = qu.front(); qu.pop(); ext[u] = false; for( int t=0; t<g[u].size(); t++) { Edge &e = edge[g[u][t]]; if( e.f && dis[e.v]>dis[e.u]+e.c ) { dis[e.v] = dis[e.u]+e.c; pth[e.v] = g[u][t]; if( !ext[e.v] ) { ext[e.v] = true; qu.push( e.v ); } } } } if( dis[dst]==oo ) return false; int flw = oo; for( int eid=pth[dst]; eid!=-1; eid=pth[edge[eid].u] ) flw = min( flw, edge[eid].f ); for( int eid=pth[dst]; eid!=-1; eid=pth[edge[eid].u] ) { edge[eid].f -= flw; edge[eid^1].f += flw; } flow += flw; cost += flw*dis[dst]; return true; } void mcmf( int &flow, int &cost ) { flow = cost = 0; while( spfa(flow,cost) ); } }; int n, m; Mcmf M; int main() { int cas; scanf( "%d", &cas); while(cas--) { scanf( "%d%d", &n, &m); int s = 0, t = n*2+1; M.init(t+1, s, t); for(int i = 1;i<=m;i++) { int u, v, cos; scanf("%d%d%d", &u, &v, &cos); M.add_edge(u, v+n, cos, 1); } for(int i = 1;i<=n;i++) { M.add_edge(M.src, i, 0, 1); M.add_edge(i+n, M.dst, 0, 1); } int flow, cost; M.mcmf(flow, cost); printf("%d\n", cost); } return 0; }
相关文章推荐
- Windows程序设计(消息机制)
- 黑马程序员-数据类型、变量作用域和数据结构的学习笔记
- hdu 1203 dp背包问题
- 对C++中迭代器的分类的认识
- Oracle学习(4):分组函数
- 线程池
- TestNG超详细教程
- ngx_http_concat_module
- 五步学会Android的ListView控件
- hdu 2093 考试排名(结构体排序)
- 傻瓜的SPI的通信
- openstack ecosystem
- 五月学习感悟
- 大盘暴跌是赚钱的什么好机会?
- 疯狂Java学习笔记(57)------------NIO:浅析I/O模型
- 疯狂Java学习笔记(58)-----------NIO概述
- 虚拟化基础知识
- awk命令详解
- 将github上的工程导入到Myeclipse中
- oracle 优化器之执行计划