2521: [Shoi2010]最小生成树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 445  Solved: 262
[Submit][Status][Discuss]

Description

Secsa最近对最小生成树问题特别感兴趣。他已经知道如果要去求出一个n个点、m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法。另外,他还知道,某一个图可能有多种不同的最小生成树。例如,下面图 3中所示的都是图 2中的无向图的最小生成树:
 
 

当然啦,这些都不是今天需要你解决的问题。Secsa想知道对于某一条无向图中的边AB,至少需要多少代价可以保证AB边在这个无向图的最小生成树中。为了使得AB边一定在最小生成树中,你可以对这个无向图进行操作,一次单独的操作是指:先选择一条图中的边 P1P2,再把图中除了这条边以外的边,每一条的权值都减少1。如图 4所示就是一次这样的操作:

Input

输入文件的第一行有3个正整数n、m、Lab分别表示无向图中的点数、边数、必须要在最小生成树中出现的AB边的标号。
接下来m行依次描述标号为1,2,3…m的无向边,每行描述一条边。每个描述包含3个整数x、y、d,表示这条边连接着标号为x、y的点,且这条边的权值为d。
输入文件保证1<=x,y<=N,x不等于y,且输入数据保证这个无向图一定是一个连通图。

Output

输出文件只有一行,这行只有一个整数,即,使得标号为Lab边一定出现最小生成树中的最少操作次数。

Sample Input

4 6 1
1 2 2
1 3 2
1 4 3
2 3 2
2 4 4
3 4 5

Sample Output

1

HINT

第1个样例就是问题描述中的例子。

1<=n<=500,1<=M<=800,1<=D<10^6

Source

[Submit][Status][Discuss]

题目中的操作——将除这条边外所有其他边的权值全部+1——就是忽悠人的,等价于将这条边的权值+1。

利用Kruskal算法的思想,如果将所有边按照权值从小到大排序后,排在指定边之前(包括和指定边权值相同)的边能使得指定边的两点联通,则指定边一定不会被选中。将一条边从指定边之前移走的最小代价就是使得其变得严格大于指定边,插值是$Val_{id}-Val_{i}+1$。把代价作为容量,跑最小割即可。

  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. inline char nextChar(void)
  5. {
  6. static const int siz = << ;
  7.  
  8. static char buf[siz];
  9. static char *hd = buf + siz;
  10. static char *tl = buf + siz;
  11.  
  12. if (hd == tl)
  13. fread(hd = buf, , siz, stdin);
  14.  
  15. return *hd++;
  16. }
  17.  
  18. inline int nextInt(void)
  19. {
  20. register int ret = ;
  21. register bool neg = false;
  22. register char bit = nextChar();
  23.  
  24. for (; bit < ; bit = nextChar());
  25. if (bit == '-')neg ^= true;
  26.  
  27. for (; bit > ; bit = nextChar())
  28. ret = ret * + bit - '';
  29.  
  30. return neg ? -ret : ret;
  31. }
  32.  
  33. const int siz = ;
  34. const int edg = 2e6 + ;
  35. const int inf = 2e9 + ;
  36.  
  37. int n, m, id, s, t;
  38.  
  39. struct edge
  40. {
  41. int x, y, w;
  42. }e[edg];
  43.  
  44. int hd[siz], to[edg], nt[edg], fl[edg], tot;
  45.  
  46. inline void add(int u, int v, int f)
  47. {
  48. nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; hd[u] = tot++;
  49. nt[tot] = hd[v]; to[tot] = u; fl[tot] = ; hd[v] = tot++;
  50. }
  51.  
  52. int dep[siz];
  53.  
  54. inline bool bfs(void)
  55. {
  56. static int que[siz];
  57. static int head, tail;
  58.  
  59. memset(dep, , sizeof(dep));
  60.  
  61. que[head = ] = s, tail = dep[s] = ;
  62.  
  63. while (head != tail)
  64. {
  65. int u = que[head++], v;
  66.  
  67. for (int i = hd[u]; ~i; i = nt[i])
  68. if (!dep[v = to[i]] && fl[i])
  69. dep[que[tail++] = v] = dep[u] + ;
  70. }
  71.  
  72. return dep[t];
  73. }
  74.  
  75. int cur[siz];
  76.  
  77. inline int min(int a, int b)
  78. {
  79. return a < b ? a : b;
  80. }
  81.  
  82. int dfs(int u, int f)
  83. {
  84. if (!f || u == t)
  85. return f;
  86.  
  87. int used = , flow, v;
  88.  
  89. for (int i = cur[u]; ~i; i = nt[i])
  90. if (dep[v = to[i]] == dep[u] + && fl[i])
  91. {
  92. flow = dfs(v, min(fl[i], f - used));
  93.  
  94. used += flow;
  95. fl[i] -= flow;
  96. fl[i^] += flow;
  97.  
  98. if (fl[i])
  99. cur[u] = i;
  100.  
  101. if (used == f)
  102. return f;
  103. }
  104.  
  105. if (!used)
  106. dep[u] = ;
  107.  
  108. return used;
  109. }
  110.  
  111. inline int minCut(void)
  112. {
  113. int minCut = , newFlow;
  114.  
  115. while (bfs())
  116. {
  117. memcpy(cur, hd, sizeof(hd));
  118.  
  119. while (newFlow = dfs(s, inf))
  120. minCut += newFlow;
  121. }
  122.  
  123. return minCut;
  124. }
  125.  
  126. signed main(void)
  127. {
  128. n = nextInt();
  129. m = nextInt();
  130.  
  131. id = nextInt();
  132.  
  133. for (int i = ; i <= m; ++i)
  134. {
  135. e[i].x = nextInt();
  136. e[i].y = nextInt();
  137. e[i].w = nextInt();
  138. }
  139.  
  140. s = e[id].x;
  141. t = e[id].y;
  142.  
  143. int lim = e[id].w;
  144.  
  145. memset(hd, -, sizeof(hd));
  146.  
  147. for (int i = ; i <= m; ++i)
  148. if (e[i].w <= lim && i != id)
  149. add(e[i].x, e[i].y, lim + - e[i].w),
  150. add(e[i].y, e[i].x, lim + - e[i].w);
  151.  
  152. printf("%d\n", minCut());
  153. }

@Author: YouSiki

BZOJ 2521: [Shoi2010]最小生成树的更多相关文章

  1. BZOJ 2521: [Shoi2010]最小生成树(最小割)

    题意 对于某一条无向图中的指定边 \((a, b)\) , 求出至少需要多少次操作.可以保证 \((a, b)\) 边在这个无向图的最小生成树中. 一次操作指: 先选择一条图中的边 \((u, v)\ ...

  2. BZOJ.2521.[SHOI2010]最小生成树(最小割ISAP/Dinic)

    题目链接 一条边不变其它边减少可以看做一条边增加其它边不变. 假设要加的边lab为(A->B,v),那么肯定是要使除这条边外,A->B的每条路径上的最小权值都\(>v\),这样在连通 ...

  3. 【BZOJ2521】[Shoi2010]最小生成树 最小割

    [BZOJ2521][Shoi2010]最小生成树 Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算 ...

  4. bzoj2521 [Shoi2010]最小生成树

    [Shoi2010]最小生成树 Time Limit: 10 Sec Memory Limit: 128 MB Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出 ...

  5. BZOJ 2521 最小生成树(最小割)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2521 题意:每次能增加一条边的权值1,求最小代价让一条边保证在最小生成树里 思路:如果两个点中有环, ...

  6. [BZOJ 1016] [JSOI2008] 最小生成树计数 【DFS】

    题目链接:BZOJ - 1016 题目分析 最小生成树的两个性质: 同一个图的最小生成树,满足: 1)同一种权值的边的个数相等 2)用Kruscal按照从小到大,处理完某一种权值的所有边后,图的连通性 ...

  7. BZOJ 2177: 曼哈顿最小生成树

    Sol 考了好几次曼哈顿最小生成树,然而一直不会打...这次终于打出来了...神tm调试了2h...好蛋疼... 首先曼哈顿最小生成树有个结论就是讲它每45度分出一个象限,对于每个点,只与每个象限中离 ...

  8. BZOJ 3732: Network 最小生成树 倍增

    3732: Network 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3732 Description 给你N个点的无向图 (1 &l ...

  9. [BZOJ]1016 JSOI2008 最小生成树计数

    最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...

随机推荐

  1. python通讯录系统

    ---恢复内容开始--- 对于一般的通讯录系统,主要有两个参数:姓名和电话号码,所以可以利用python编程里面的字典来进行建立之间的所属关系, 可以利用以下代码简单实现: print('|--- 欢 ...

  2. Hadoop源码阅读环境搭建(IDEA)

    拿到一份Hadoop源码之后,经常关注的两件事情就是 1.怎么阅读?涉及IDEA和Eclipse工程搭建.IDEA搭建,选择源码,逐步导入即可:Eclipse可以选择后台生成工程,也可以选择IDE导入 ...

  3. DQL、DML、DDL、DCL全名是啥?

    SQL(Structure Query Language)结构化查询语言 DQL(data query language)数据查询语言 select操作 DML(data manipulation l ...

  4. ltrace命令详解

    原文链接:https://ipcmen.com/ltrace 用来跟踪进程调用库函数的情况 补充说明 NAME       ltrace - A library call tracer ltrace命 ...

  5. Python 命令行解析工具 Argparse介绍

    最近在研究pathon的命令行解析工具,argparse,它是Python标准库中推荐使用的编写命令行程序的工具. 以前老是做UI程序,今天试了下命令行程序,感觉相当好,不用再花大把时间去研究界面问题 ...

  6. spring冲刺第八天

    昨天使人物成功的在地图上运动,并设计炸弹爆炸效果. 今天使炸弹可以炸死人物并可以炸没砖块,并试着将小怪加入地图. 遇到的问题:现在还没有将小怪加入地图,各个模块的整合是比较麻烦的,我还要在这方面下点功 ...

  7. 对Largest函数的测试

    题目:查找list[]中的最大值:int Largest(int list[], int length); int Largest(int list[], int length) { int i,ma ...

  8. Leetcode题库——33.搜索旋转排序数组

    @author: ZZQ @software: PyCharm @file: search.py @time: 2018/11/12 18:12 要求:假设按照升序排序的数组在预先未知的某个点上进行了 ...

  9. 超实用 1 ArrayList 链表

    package ArrayList链表; import java.util.*; public class kk1 { /** * 作者:Mr.Fan * 功能:记住ArrayList链表 */ pu ...

  10. golang type

    参考链接 https://blog.csdn.net/tzs919/article/details/53571632 type是golang中非常重要的关键字,常见的就是定义结构体,但是其功能远不止是 ...