// 给定一个有向图,必须用若干个环来覆盖整个图,要求这些覆盖的环的权值最小。

思路:原图每个点 u 拆为 u 和 u' ,从源点引容量为 1 费用为 0 的边到 u ,从 u' 引相同性质的边到汇点,若原图中存在 (u, v) ,则从 u 引容量为 1 费用为 c(u, v) 的边到 v' 。

其实这里的源模拟的是出度,汇模拟的是入度,因为环中每个点的出度等于入度等于 1 ,那么如果最大流不等于顶点数 n ,则无解;否则,答案就是最小费用。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <queue> using namespace std; const int maxn = 2e2 + ;
const int maxm = 2e4 + ;
const int inf = 0x3f3f3f3f; struct MCMF
{
struct Edge
{
int v, c, w, next;
}p[maxm << ];
int e, head[maxn], dis[maxn], pre[maxn], cnt[maxn], sumFlow, n;
bool vis[maxn];
void init(int nt)
{
e = , n = nt;
memset(head, -, sizeof(head[]) * (n + ) );
}
void addEdge(int u, int v, int c, int w)
{
p[e].v = v, p[e].c = c; p[e].w = w; p[e].next = head[u]; head[u] = e++;
swap(u, v);
p[e].v = v, p[e].c = ; p[e].w = -w; p[e].next = head[u]; head[u] = e++;
}
bool spfa(int S, int T)
{
queue <int> q;
for (int i = ; i <= n; ++i)
vis[i] = cnt[i] = , pre[i] = -, dis[i] = inf;
vis[S] = , dis[S] = ;
q.push(S);
while (!q.empty())
{
int u = q.front(); q.pop();
vis[u] = ;
for (int i = head[u]; i + ; i = p[i].next)
{
int v = p[i].v;
if (p[i].c && dis[v] > dis[u] + p[i].w)
{
dis[v] = dis[u] + p[i].w;
pre[v] = i;
if (!vis[v])
{
q.push(v);
vis[v] = ;
if (++cnt[v] > n) return ;
}
}
}
}
return dis[T] != inf;
}
int mcmf(int S, int T)
{
sumFlow = ;
int minFlow = , minCost = ;
while (spfa(S, T))
{
minFlow = inf + ;
for (int i = pre[T]; i + ; i = pre[ p[i ^ ].v ])
minFlow = min(minFlow, p[i].c);
sumFlow += minFlow;
for (int i = pre[T]; i + ; i = pre[ p[i ^ ].v ])
{
p[i].c -= minFlow;
p[i ^ ].c += minFlow;
}
minCost += dis[T] * minFlow;
}
return minCost;
}
void build(int nt, int mt)
{
init((nt << ) + );
int u, v, c;
for (int i = ; i <= nt; ++i)
{
addEdge(, i, , );
addEdge(i + nt, n, , );
}
while (mt--)
{
scanf("%d%d%d", &u, &v, &c);
addEdge(u, v + nt, , c);
}
}
void solve(int nt)
{
int ans = mcmf(, n);
if ( sumFlow != nt)
printf("-1\n");
else
printf("%d\n", ans);
}
}my; int main()
{
int n, m;
while (~scanf("%d%d", &n, &m))
{
my.build(n, m);
my.solve(n);
}
return ;
}

最新文章

  1. cmd 常用指令
  2. Scala 中的函数式编程基础(三)
  3. Servlet+Jsp实现图片或文件的上传功能
  4. [原创]java WEB学习笔记49:文件上传基础,基于表单的文件上传,使用fileuoload 组件
  5. DOJO官方API翻译或解读-dojo/store (自定制存储器)
  6. Qt窗体关闭时,如何自动销毁窗体类对象
  7. [Webpack] Use the Webpack Dashboard to Monitor Webpack Operations
  8. WIndows 7 与 Debian 7 双系统启动引导
  9. C语言学习总结(二) 运算流程
  10. 转载:遍历Map的四种方法
  11. (转载)JS中的prototype
  12. DOM 以及JS中的事件
  13. windows粘贴板操作-自己的应用和windows右键互动
  14. 知其所以然~redis的原子性
  15. [ Talk is Cheap Show me the CODE ] : jQuery Mobile页面布局
  16. SpringBoot集成Freemarker与Thymeleaf
  17. 用jquery得到select选中的值
  18. flex 布局下,css 设置文本不换行时,省略号不显示的解决办法
  19. HDU 4352 - XHXJ&#39;s LIS - [数位DP][LIS问题]
  20. freemarker多个checkbox一个以上被选中示例

热门文章

  1. 补番计划 (长沙理工大学第十一届程序设计竞赛)(双端队列+set容器+string)
  2. Node.js meitulu图片批量下载爬虫1.04版
  3. Java8 更快的原子类:LongAdder(笔记)
  4. ColorSchemer Studio 2 破解
  5. TP框架I方法详解
  6. ACE_Task::putq(转)
  7. scp命令使下用
  8. Oracle 和sqlserver 字符串补齐
  9. 切换默认Activity和Fragment的动画
  10. HttpClient POST 的 UTF-8 编码问题