Problem Description

度度熊国王率领着喵哈哈族的勇士,准备进攻哗啦啦族。

哗啦啦族是一个强悍的民族,里面有充满智慧的谋士,拥有无穷力量的战士。

所以这一场战争,将会十分艰难。

为了更好的进攻哗啦啦族,度度熊决定首先应该从内部瓦解哗啦啦族。

第一步就是应该使得哗啦啦族内部不能同心齐力,需要内部有间隙。

哗啦啦族一共有n个将领,他们一共有m个强关系,摧毁每一个强关系都需要一定的代价。

现在度度熊命令你需要摧毁一些强关系,使得内部的将领,不能通过这些强关系,连成一个完整的连通块,以保证战争的顺利进行。

请问最少应该付出多少的代价。

Input

本题包含若干组测试数据。

第一行两个整数n,m,表示有n个将领,m个关系。

接下来m行,每行三个整数u,v,w。表示u将领和v将领之间存在一个强关系,摧毁这个强关系需要代价w

数据范围:

2<=n<=3000

1<=m<=100000

1<=u,v<=n

1<=w<=1000


题目大意:求全局最小割。

题解:就是一标准的Stoer-Wagner算法模板题,邻接表法理论复杂度\(O(nm \log(m))\)。见:全局最小割StoerWagner算法详解

PS:网上绝大部分题解是错误的,反例很容易能找出。但是却能AC,可以看出此次百度之星的出题人非常不认真啊。

代码(6770MS):

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <numeric> typedef long long LL; const int MAXV = 3010;
const int MAXE = 100010 * 2;
const int INF = 0x3f3f3f3f; int head[MAXV], val[MAXV], ecnt;
int to[MAXE], next[MAXE], weight[MAXE];
bool vis[MAXV];
int fa[MAXV], link[MAXV];
int n, m; void init() {
memset(head + 1, -1, sizeof(int) * n);
memset(link + 1, -1, sizeof(int) * n);
for (int i = 1; i <= n; ++i)
fa[i] = i;
ecnt = 0;
} void add_edge(int u, int v, int w) {
to[ecnt] = v; weight[ecnt] = w; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; weight[ecnt] = w; next[ecnt] = head[v]; head[v] = ecnt++;
} int findset(int u) { // 并查集
return u == fa[u] ? u : fa[u] = findset(fa[u]);
} void merge(int u, int v) {
int p = u;
while (~link[p]) p = link[p];
link[p] = v;
fa[v] = u;
} int MinimumCutPhase(int cnt, int &s, int &t) {
memset(val + 1, 0, sizeof(int) * n);
memset(vis + 1, 0, sizeof(bool) * n);
std::priority_queue<std::pair<int, int>> que;
t = 1;
while (--cnt) {
vis[s = t] = true;
for (int u = s; ~u; u = link[u]) {
for (int p = head[u]; ~p; p = next[p]) {
int v = findset(to[p]);
if (!vis[v])
que.push(std::make_pair(val[v] += weight[p], v));
}
}
t = 0;
while (!t) {
if (que.empty()) return 0; // 图不连通
auto pa = que.top(); que.pop();
if (val[pa.second] == pa.first)
t = pa.second;
}
}
return val[t];
} int StoerWagner() {
int res = INF;
for (int i = n, s, t; i > 1; --i) {
res = std::min(res, MinimumCutPhase(i, s, t));
if (res == 0)
break;
merge(s, t);
}
return res;
} int main() {
while (scanf("%d%d", &n, &m) != EOF) {
init();
for (int i = 0, u, v, w; i < m; ++i) {
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
}
printf("%d\n", StoerWagner());
}
}

顺便试一下pb_ds库,详见IOI集训队论文《C++的pb_ds库在OI中的应用——于纪平》

pb_ds优先队列学习笔记

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <numeric>
#include <ext/pb_ds/priority_queue.hpp> typedef long long LL; /// 都只试了一次,不一定准确
//typedef __gnu_pbds::priority_queue<std::pair<int, int>, std::less<std::pair<int, int>>, __gnu_pbds::binary_heap_tag> PQue; // TLE
//typedef __gnu_pbds::priority_queue<std::pair<int, int>, std::less<std::pair<int, int>>, __gnu_pbds::binomial_heap_tag> PQue; // 7940MS
//typedef __gnu_pbds::priority_queue<std::pair<int, int>, std::less<std::pair<int, int>>, __gnu_pbds::rc_binomial_heap_tag> PQue; // 9204MS
//typedef __gnu_pbds::priority_queue<std::pair<int, int>, std::less<std::pair<int, int>>, __gnu_pbds::pairing_heap_tag> PQue; // 6770MS
typedef __gnu_pbds::priority_queue<std::pair<int, int>, std::less<std::pair<int, int>>, __gnu_pbds::thin_heap_tag> PQue; // 8954MS const int MAXV = 3010;
const int MAXE = 100010 * 2;
const int INF = 0x3f3f3f3f; int head[MAXV], val[MAXV], ecnt;
int to[MAXE], next[MAXE], weight[MAXE];
bool vis[MAXV];
int fa[MAXV], link[MAXV];
PQue::point_iterator iter[MAXV];
int n, m; void init() {
memset(head + 1, -1, sizeof(int) * n);
memset(link + 1, -1, sizeof(int) * n);
for (int i = 1; i <= n; ++i)
fa[i] = i;
ecnt = 0;
} void add_edge(int u, int v, int w) {
to[ecnt] = v; weight[ecnt] = w; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; weight[ecnt] = w; next[ecnt] = head[v]; head[v] = ecnt++;
} int findset(int u) { // 并查集
return u == fa[u] ? u : fa[u] = findset(fa[u]);
} void merge(int u, int v) { // 合并
int p = u;
while (~link[p]) p = link[p];
link[p] = v;
fa[v] = u;
} int MinimumCutPhase(int cnt, int &s, int &t) {
memset(val + 1, 0, sizeof(int) * n);
memset(vis + 1, 0, sizeof(bool) * n);
PQue que;
for (int i = 1; i <= n; ++i)
iter[i] = 0;
t = 1;
while (--cnt) {
vis[s = t] = true;
for (int u = s; ~u; u = link[u]) {
for (int p = head[u]; ~p; p = next[p]) {
int v = findset(to[p]);
if (!vis[v]) {
if (iter[v] != 0)
que.modify(iter[v], std::make_pair(val[v] += weight[p], v));
else
iter[v] = que.push(std::make_pair(val[v] += weight[p], v));
}
}
} if (que.empty()) return 0; // 图不连通
t = que.top().second; que.pop();
}
return val[t];
} int StoerWagner() {
int res = INF;
for (int i = n, s, t; i > 1; --i) {
res = std::min(res, MinimumCutPhase(i, s, t));
if (res == 0)
break;
merge(s, t);
}
return res;
} int main() {
while (scanf("%d%d", &n, &m) != EOF) {
init();
for (int i = 0, u, v, w; i < m; ++i) {
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
}
printf("%d\n", StoerWagner());
}
}

HDU 6081 度度熊的王国战略(全局最小割Stoer-Wagner算法)的更多相关文章

  1. HDU 6081 度度熊的王国战略(全局最小割堆优化)

    Problem Description度度熊国王率领着喵哈哈族的勇士,准备进攻哗啦啦族.哗啦啦族是一个强悍的民族,里面有充满智慧的谋士,拥有无穷力量的战士.所以这一场战争,将会十分艰难.为了更好的进攻 ...

  2. HDU 6081 度度熊的王国战略【并查集/数据弱水题/正解最小割算法】

    链接6081 度度熊的王国战略 Time Limit: 40000/20000 MS (Java/Others) Memory Limit: 32768/132768 K (Java/Others) ...

  3. HDU - 6081 2017百度之星资格赛 度度熊的王国战略

    度度熊的王国战略  Accepts: 644  Submissions: 5880  Time Limit: 40000/20000 MS (Java/Others)  Memory Limit: 3 ...

  4. 2017"百度之星"程序设计大赛 - 资格赛 度度熊的王国战略

    度度熊的王国战略 度度熊国王率领着喵哈哈族的勇士,准备进攻哗啦啦族. 哗啦啦族是一个强悍的民族,里面有充满智慧的谋士,拥有无穷力量的战士. 所以这一场战争,将会十分艰难. 为了更好的进攻哗啦啦族,度度 ...

  5. 2017"百度之星"程序设计大赛 - 资格赛 1002 度度熊的王国战略

    全局最小割 Stoer-Wagner (SW算法)优化 优化吃藕了,感谢放宽时限,感谢平板电视 (pb_ds) #include <iostream> #include <cstdi ...

  6. 求全局最小割(SW算法)

    hdu3002 King of Destruction Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  7. HDU 6118 度度熊的交易计划 【最小费用最大流】 (2017"百度之星"程序设计大赛 - 初赛(B))

    度度熊的交易计划 Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  8. HDU 6118 度度熊的交易计划(网络流-最小费用最大流)

    度度熊参与了喵哈哈村的商业大会,但是这次商业大会遇到了一个难题: 喵哈哈村以及周围的村庄可以看做是一共由n个片区,m条公路组成的地区. 由于生产能力的区别,第i个片区能够花费a[i]元生产1个商品,但 ...

  9. 图的全局最小割的Stoer-Wagner算法及例题

    Stoer-Wagner算法基本思想:如果能求出图中某两个顶点之间的最小割,更新答案后合并这两个顶点继续求最小割,到最后就得到答案. 算法步骤: --------------------------- ...

随机推荐

  1. 0基础的人如何入门 Python ?Python难么?

    人生苦短,我用Python,为啥这么说,因为我们自动化测试有金句:学完Python,便可上天 ~ 废话不多说,相信很多人都听过之前的Python进入小学课本.Python进入浙江省高考等新闻,有这么多 ...

  2. python解析式

    一.列表解析式 列表解析是外面一对中括号,它返回的是列表. 一般形式为:[expr for item in itratoble] print([i+1 for i in range(10)]) #结果 ...

  3. python第四十课——构造函数

    1.动态给对象添加属性: 在对象创建完毕后,单独为其添加需要的属性:可以理解为:私人定制 [注意]: 添加的属性只有此对象能够使用,别的对象如果用了,直接报错; 2.构造函数/构造方法/构造器: 格式 ...

  4. python第二十六课——装饰器

    装饰器是闭包的一种使用场景: python中的装饰器在定义上需要传入一个函数对象, 在此函数执行之前或者之后都可以追加其它的操作, 这样做的好处是,在不改变源码(原本业务逻辑的)同时,进行功能的扩展: ...

  5. iosclient发现_世界杯送流量活动项目总结

       世界杯如火如荼的进行.视频站点相似于门户站点.须要高速依据外部环境更新内容. 产品经理须要策划活动,并安排实施.这个活动就是在这样背景下产生的,爱奇艺与运营商合作,实现双赢.爱奇艺能够通过运营商 ...

  6. 如何快速找到某个研究领域的所有SCI期刊

    https://www.toutiao.com/a6624332265285485060/?tt_from=dingtalk&utm_campaign=client_share&tim ...

  7. vector,deque,list的区别和使用

    vector: 表示一段连续的内存区域,每个元素被顺序存储在这段内存中,对vector的随机访问效率很高,但对非末尾元素的插入和删除则效率非常低. deque: 也表示N段连续的内存区域组成,但与ve ...

  8. 如何在Drupal7中用代码批量创建节点、评论和分类

    最近,我忙于一个网站迁移工作.网站是使用某个老式CMS建立的,有一定数量的文章.不同的分类数据和用户评论.我的团队被雇来把这些数据从这个浪费人力物力的老式CMS上完整的迁移到功能更现代的开源Drupa ...

  9. Dozer 使用小结

    这篇文章是本人在阅读Dozer官方文档(5.5.1版本,官网已经一年多没更新了)的过程中,整理下来我认为比较基础的应用场景. 本文中提到的例子应该能覆盖JavaBean映射的大部分场景,希望对你有所帮 ...

  10. 使用XMing+putty运行linux图形界面程序

    起因接下去的工作要作一些数值模拟,于是到师兄的工作站上开了个帐号.工作站运行的是RHEL4,要说远程SSH,就算是FTerm也足够胜任,不过,因为我要用的查看计算结果的软件需要使用图形界面,这一点就比 ...