题意:N个点。M条边(2 <= N <= 1000 , 0 <= M <= 10^5),每一个点有个权值W(0 <= W <= 10^5),现要去除一些点(不能去掉点0),使得结点 0 与结点 N - 1 不连通,求去掉的点的最小权值和。

题目链接:http://cstest.scu.edu.cn/soj/problem.action?id=3254

——>>这是很明显的最小点权割。。

建图方案:

1)将全部点 i 拆成 i 和 i + N。i -> i + N(容量为Wi)

2)原图中的边 i -> j 变成 i + N -> j(容量为无穷大)

3)0 -> 0 + N(由于原图中的边可能有涉及到0 -> x,这时会拆0)

接着,依据最小割最大流定理。求得最小割。。(又换命名法了我。囧。。)

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <queue>
  4. #include <algorithm>
  5.  
  6. using std::min;
  7. using std::queue;
  8.  
  9. const int MAXN = 1000 * 2 + 10;
  10. const int MAXM = 2 * (1000 + 100000) + 10;
  11. const int INF = 0x3f3f3f3f;
  12.  
  13. struct EDGE
  14. {
  15. int to;
  16. int cap;
  17. int flow;
  18. int nxt;
  19. };
  20.  
  21. int N, M;
  22. int hed[MAXN], nxt[MAXM], S, T;
  23. int cur[MAXN], h[MAXN];
  24. bool vis[MAXN];
  25. int ecnt;
  26. EDGE edge[MAXM];
  27.  
  28. void Init()
  29. {
  30. ecnt = 0;
  31. memset(hed, -1, sizeof(hed));
  32. }
  33.  
  34. void AddEdge(int u, int v, int cap)
  35. {
  36. edge[ecnt].to = v;
  37. edge[ecnt].cap = cap;
  38. edge[ecnt].flow = 0;
  39. edge[ecnt].nxt = hed[u];
  40. hed[u] = ecnt++;
  41. }
  42.  
  43. bool Bfs()
  44. {
  45. queue<int> qu;
  46.  
  47. memset(vis, 0, sizeof(vis));
  48. qu.push(S);
  49. vis[S] = true;
  50. h[S] = 0;
  51. while (!qu.empty())
  52. {
  53. int u = qu.front();
  54. qu.pop();
  55. for (int e = hed[u]; e != -1; e = edge[e].nxt)
  56. {
  57. int v = edge[e].to;
  58. if (!vis[v] && edge[e].flow < edge[e].cap)
  59. {
  60. h[v] = h[u] + 1;
  61. vis[v] = true;
  62. qu.push(v);
  63. }
  64. }
  65. }
  66.  
  67. return vis[T];
  68. }
  69.  
  70. int Dfs(int u, int cap)
  71. {
  72. if (u == T || cap == 0) return cap;
  73.  
  74. int flow = 0, subFlow;
  75. for (int e = cur[u]; e != -1; e = edge[e].nxt)
  76. {
  77. cur[u] = e;
  78. int v = edge[e].to;
  79. if (h[v] == h[u] + 1 && (subFlow = Dfs(v, min(cap, edge[e].cap - edge[e].flow))) > 0)
  80. {
  81. flow += subFlow;
  82. edge[e].flow += subFlow;
  83. edge[e ^ 1].flow -= subFlow;
  84. cap -= subFlow;
  85. if (cap == 0) break;
  86. }
  87. }
  88.  
  89. return flow;
  90. }
  91.  
  92. int Dinic()
  93. {
  94. int flow = 0;
  95.  
  96. while (Bfs())
  97. {
  98. memcpy(cur, hed, sizeof(hed));
  99. flow += Dfs(S, INF);
  100. }
  101.  
  102. return flow;
  103. }
  104.  
  105. void Read()
  106. {
  107. int W;
  108. scanf("%d%d", &N, &M);
  109. for (int i = 1; i < N; ++i)
  110. {
  111. scanf("%d", &W);
  112. AddEdge(i, i + N, W);
  113. AddEdge(i + N, i, 0);
  114. }
  115. int P, Q;
  116. for (int i = 0; i < M; ++i)
  117. {
  118. scanf("%d%d", &P, &Q);
  119. AddEdge(P + N, Q, INF);
  120. AddEdge(Q, P + N, 0);
  121. }
  122. AddEdge(0, N, INF);
  123. AddEdge(N, 0, 0);
  124. S = 0;
  125. T = 2 * N - 1;
  126. }
  127.  
  128. void Solve()
  129. {
  130. printf("%d\n", Dinic());
  131. }
  132.  
  133. int main()
  134. {
  135. int T;
  136.  
  137. scanf("%d", &T);
  138. while (T--)
  139. {
  140. Init();
  141. Read();
  142. Solve();
  143. }
  144.  
  145. return 0;
  146. }

scu - 3254 - Rain and Fgj(最小点权割)的更多相关文章

  1. POJ 2125 Destroying the Graph 二分图最小点权覆盖

    Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8198   Accepted: 2 ...

  2. POJ3308 Paratroopers(最小割/二分图最小点权覆盖)

    把入侵者看作边,每一行每一列都是点,选取某一行某一列都有费用,这样问题就是选总权最小的点集覆盖所有边,就是最小点权覆盖. 此外,题目的总花费是所有费用的乘积,这时有个技巧,就是取对数,把乘法变为加法运 ...

  3. HDU 3491 最小点权割集

    题意:有n个城市,m条双向边,有一群小偷从s前往t偷东西,警察叔叔们想要逮捕小偷们,现在告诉你在每座城市需要多少警察才能抓住这个城市的小偷,为什么说这个城市,因为小偷们会分开跑:然后题目还说不能在s和 ...

  4. POJ2125 Destroying The Graph(二分图最小点权覆盖集)

    最小点权覆盖就是,对于有点权的有向图,选出权值和最少的点的集合覆盖所有的边. 解二分图最小点权覆盖集可以用最小割: vs-X-Y-vt这样连边,vs和X部点的连边容量为X部点的权值,Y部和vt连边容量 ...

  5. POJ2125 Destroying The Graph (最小点权覆盖集)(网络流最小割)

                                                          Destroying The Graph Time Limit: 2000MS   Memo ...

  6. POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)

    题意 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少. 思路 很明显的二分图最小点权覆盖 ...

  7. POJ 3308 Paratroopers (对数转换+最小点权覆盖)

    题意 敌人侵略r*c的地图.为了消灭敌人,可以在某一行或者某一列安置超级大炮.每一个大炮可以瞬间消灭这一行(或者列)的敌人.安装消灭第i行的大炮消费是ri.安装消灭第j行的大炮消费是ci现在有n个敌人 ...

  8. POJ2125 Destroying The Graph 二分图 + 最小点权覆盖 + 最小割

    思路来源:http://blog.csdn.net/lenleaves/article/details/7873441 求最小点权覆盖,同样求一个最小割,但是要求出割去了那些边, 只要用最终的剩余网络 ...

  9. poj3308 Paratroopers --- 最小点权覆盖-&gt;最小割

    题目是一个非常明显的二分图带权匹配模型, 加入源点到nx建边,ny到汇点建边,(nx.ny)=inf建边.求最小割既得最小点权覆盖. 在本题中因为求的是乘积,所以先所有取log转换为加法,最后再乘方回 ...

随机推荐

  1. UltraEdit配置python和lua环境

    [语法高亮] 在UltraEdit的wordfile中添加python和lua的语法支持(红色的为python,蓝色的为lua): /L10"Python" Line Commen ...

  2. uva 657

    很简单的题,就是题意不懂……! 就是判断每个'*'区域内‘X’区域块的个数 WA了好多次,就是太差了: 1.结果排序输出 2.因为是骰子所以不再1-6范围内的数字要舍弃 3.格式要求要空一行…… 4. ...

  3. C++,Python,Go对照学习-02

    main函数         Go中有且只有一个main函数,而且main函数必须在package main当中.main函数无返回值也无参数,如果希望获取从命令行传递的参数有其他包解决这个问题.   ...

  4. Java_io体系之BufferedWriter、BufferedReader简介、走进源码及示例——16

    Java_io体系之BufferedWriter.BufferedReader简介.走进源码及示例——16 一:BufferedWriter 1.类功能简介: BufferedWriter.缓存字符输 ...

  5. 配置QtCreator+CDB远程调试环境(要设置_NT_SYMBOL_PATH和QT_PLUGIN_PATH和Path)

    相关环境信息:开发机Win7 x64.远程机器WinXP.调试器是CDB.Qt版本5.2.1 一.部署远程机器环境 我这里用的是虚拟机(Windows XP),根据你要调试的程序选择安装不同架构的Wi ...

  6. UVA 116 Unidirectional TSP(dp + 数塔问题)

     Unidirectional TSP  Background Problems that require minimum paths through some domain appear in ma ...

  7. Swift - 多行文本输入框(UITextView)的用法

    1,多行文本控件的创建 1 2 3 4 var textview=UITextView(frame:CGRectMake(10,100,200,100)) textview.layer.borderW ...

  8. ruby语言仅仅是昙花一现

    Ruby语言本身存在非常久了,在国内一直没火过.非常多人仅仅是知道有这样的语言,会的人少之又少.不论什么一种语言坚持十来年的发展,变得越来越好,一定有它不平常的地方.不能任意的去比較语言本身的好与坏. ...

  9. Java的一些基础小知识之JVM与GC (转)

    一.JVM是什么 Java虚拟机(英语:Java Virtual Machine,缩写为JVM),又名爪哇虚拟器,一种能够运行Java bytecode的虚拟机,以堆栈结构机器来进行实做.最早由太阳微 ...

  10. 例3.1 猜猜数据结构 UVa11995

    1.标题叙述性说明:点击打开链接 2.解题思路:据来推測一种可能的数据结构,备选答案有"栈,队列.优先队列".结果也可能都不是或者不确定. STL中已经有这三种数据结构了,因此直接 ...