##最小环定义
最小环是指在一个图中,有n个节点构成的边权和最小的环(n>=3)。
一般来说,最小环分为有向图最小环和无向图最小环。
##最小环算法:
###直接暴力:
设$u$和$v$之间有一条边长为$w$的边,$dis(u,v)$表示删除$u$和$v$之间的连边之后,$u$和$v$之间的最短路。那么最小环是$dis(u,v)+w$总时间复杂度$O(n^2m)$。
###Dijkstra
任意一个环,假设连接$u$和$v$,我们都可以看做删除$u$与$v$的直接连边之后的$u$到$v$的最短路再加上该边,若边数为$m$,那么找出最小环要跑$m$次Dijkstra,复杂度为$O(n(n+m)log)$
###Floyd
记原图$u$,$v$之间边权为$mp(u,v)$,floyd算法在外层循环到第k个点时(还没开始第k次循环),最短路数组$g$中,$g(u,v)$表示的是从$u$到$v$且仅经过编号$[1,k)$区间中的点的最短路。
最小环至少有三个顶点,设其中编号最大的顶点编号为$w$,环上与$w$相邻两侧的两个点为$u$,\(v\),则在最外层循环枚举到$k=w$时,该环的长度为$g(u,v)+mp(v,w)+mp(w,u)$,所以在循环时候$i$,$j$只需枚举到$i<k$,\(j<k\),更新答案即可
复杂度:\(O(n^3)\)
##下面是实现参考:

  for (int k = 1; k <= n; k++)
{
for (int i = 1; i < k; i++)
for (int j = i + 1; j < k; j++)
ans = min(ans, g[i][j] + mp[i][k] + mp[k][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}

##例题 HDU 1599
此处输入链接的描述
裸题= =,没啥东西,就去个重

#include <bits/stdc++.h>
using namespace std;
/* freopen("k.in", "r", stdin);
freopen("k.out", "w", stdout); */
//clock_t c1 = clock();
//std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 1e2 + 7;
const ll MAXM = 1e6 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
ll g[MAXN][MAXN];
ll mp[MAXN][MAXN]; //原图
int n, m;
void init()
{
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
mp[i][j] = i == j ? 0 : inf;
}
int main()
{
while (~scanf("%d%d", &n, &m))
{
init();
memset(g, inf, sizeof(g));
for (int i = 0; i < m; i++)
{
int u, v;
ll val;
scanf("%d%d%lld", &u, &v, &val);
if (val < mp[u][v])
mp[v][u] = mp[u][v] = val;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
g[i][j] = mp[i][j];
ll ans = inf;
for (int k = 1; k <= n; k++)
{
for (int i = 1; i < k; i++)
for (int j = i + 1; j < k; j++)
ans = min(ans, g[i][j] + mp[i][k] + mp[k][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}
if (ans == inf)
printf("It's impossible.\n");
else
printf("%d\n", ans);
}
return 0;
}

参考oiwiki
##dijkstra版拓展题 HDU-6005 Pandaland
HDU6005
###解题思路:
也是最小环(当然啦啊喂),不过点是坐标的形式,需要转换为序号,之后记录跑的起点和终点,dijkstra中不跑这条边即可,可以稍微剪剪枝(超重要诶),如果dijkstra中当前最短边和直连边权值之和大于ans,直接break,会快很多(迫真),这题没重边,所以不用去

#include <bits/stdc++.h>
using namespace std;
/* freopen("k.in", "r", stdin);
freopen("k.out", "w", stdout); */
//clock_t c1 = clock();
//std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 8e3 + 7;
const ll MAXM = 1e6 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
struct node
{
int v, c;
node(int a = 0, int b = 0) { v = a, c = b; }
bool operator<(const node &a) const
{
if (c == a.c)
return v < a.v;
else
return c > a.c;
}
};
struct Edge
{
int v, cost;
Edge(int _v = 0, int _cost = 0) { v = _v, cost = _cost; }
};
struct EE
{
int u, v, w;
EE(int _u = 0, int _v = 0, int _w = 0) { u = _u, v = _v, w = _w; }
} E[MAXN];
vector<Edge> G[MAXN];
bool vis[MAXN];
int dist[MAXN];
//点的编号从1开始
int ans;
void Dijkstra(int n, int start, int ed, int val)
{
memset(vis, false, sizeof(vis));
for (int i = 1; i <= n; i++)
dist[i] = inf;
priority_queue<node> que;
while (!que.empty())
que.pop();
dist[start] = 0;
que.push(node(start, 0));
node temp;
while (!que.empty())
{
temp = que.top();
que.pop();
int u = temp.v;
if (temp.c + val > ans)
break; //该点最短距离+start与ed的直连边长大于ans,说明不是最小环,直接break
if (vis[u])
continue;
vis[u] = true;
for (int i = 0; i < G[u].size(); i++)
{
int v = G[u][i].v;
int cost = G[u][i].cost;
if ((u == start && v == ed) || (v == ed && u == start)) //不经过start-ed的直达边
continue;
if (!vis[v] && dist[v] > dist[u] + cost)
{
dist[v] = dist[u] + cost;
que.push(node(v, dist[v]));
}
}
}
}
void addedge(int u, int v, int w)
{
G[u].push_back(Edge(v, w));
}
int cnt = 0;
void init(int n)
{
for (int i = 1; i <= n; i++)
G[i].clear();
cnt=0;
}
/* 题目没重边,不然还得去一波重 */
int main()
{
int t;
scanf("%d", &t);
for (int tt = 1; tt <= t; tt++)
{
map<PII, int> mp;
int m;
scanf("%d", &m);
init(m << 1);
for (int i = 0; i < m; i++)
{
int x1, y1, x2, y2, w;
scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &w);
if (!mp[PII(x1, y1)])
mp[PII(x1, y1)] = ++cnt;
if (!mp[PII(x2, y2)])
mp[PII(x2, y2)] = ++cnt;
int u = mp[PII(x1, y1)], v = mp[PII(x2, y2)];
addedge(u, v, w);
addedge(v, u, w);
E[i] = EE(u, v, w); //存原边
}
ans = inf;
for (int i = 0; i < m; i++)
{
if (ans < E[i].w)
continue;
Dijkstra(cnt, E[i].u, E[i].v, E[i].w);
ans = min(ans, dist[E[i].v] + E[i].w);
}
printf("Case #%d: %d\n", tt, ans == inf ? 0 : ans);
}
return 0;
}

最小环(floyd以及dijkstra实现+例题)的更多相关文章

  1. hdu1874 畅通project续 最短路 floyd或dijkstra或spfa

    Problem Description 某省自从实行了非常多年的畅通project计划后.最终修建了非常多路.只是路多了也不好,每次要从一个城镇到还有一个城镇时,都有很多种道路方案能够选择.而某些方案 ...

  2. 图论——最短路:Floyd,Dijkstra,Bellman-Ford,SPFA算法及最小环问题

    一.Floyd算法 用于计算任意两个节点之间的最短路径. 参考了five20的博客 Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个 ...

  3. timus1004 最小环()Floyd 算法

    通过别人的数据搞了好久才成功,果然还是不够成熟 做题目还是算法不能融会贯通 大意即找出图中至少3个顶点的环,且将环中点按顺序输出 用floyd算法求最小环 因为floyd算法求最短路径是通过中间量k的 ...

  4. 最小生成树(prime算法 & kruskal算法)和 最短路径算法(floyd算法 & dijkstra算法)

    一.主要内容: 介绍图论中两大经典问题:最小生成树问题以及最短路径问题,以及给出解决每个问题的两种不同算法. 其中最小生成树问题可参考以下题目: 题目1012:畅通工程 http://ac.jobdu ...

  5. 图论之最短路径(1)——Floyd Warshall & Dijkstra算法

    开始图论学习的第二部分:最短路径. 由于知识储备还不充足,暂时不使用邻接表的方法来计算. 最短路径主要分为两部分:多源最短路径和单源最短路径问题 多源最短路径: 介绍最简单的Floyd Warshal ...

  6. 最短路径——Floyd,Dijkstra(王道)

    题目描述: 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线 ...

  7. 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较

        几大最短路径算法比较 转自:http://blog.csdn.net/v_july_v/article/details/6181485 几个最短路径算法的比较: Floyd        求多 ...

  8. 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较(转)

    几大最短路径算法比较 几个最短路径算法的比较:Floyd        求多源.无负权边(此处错误?应该可以有负权边)的最短路.用矩阵记录图.时效性较差,时间复杂度O(V^3).       Floy ...

  9. 图的连通性问题之连通和最小环——Floyd算法

    Floyd 判断连通性 d[i][j]仅表示i,j之间是否联通 ;k<=n;k++) ;i<=n;i++) ;j<=n;j++) dis[i][j]=dis[i][j]||(dis[ ...

随机推荐

  1. 常见的java异常——java.lang.IllegalStateException: Ambiguous handler methods mapped for HTTP path

    此异常是由于你的controller中有两个名字与内容相同的方法: 出现此异常时去检查你的controller中是否有重复的名字的方法:

  2. Python 元类的基本介绍及使用

    一.什么是元类 二.如何使用元类 (一)不依赖class关键字创建一个自定义类 (二)自定义元类控制类的产生 (三)自定义元类控制类的调用 一.什么是元类 在python中,一切皆对象,而对象都是由类 ...

  3. 洛谷$2014$ 选课 背包类树形$DP$

    luogu Sol 阶段和状态都是树形DP板子题,这里只讲一下背包的部分(转移)叭 它其实是一个分组背包模型,具体理解如下: 对于一个结点x,它由它的子结点y转移而来 在子结点y为根的树中可以选不同数 ...

  4. 机器学习实战笔记(一)- 使用SciKit-Learn做回归分析

    一.简介 这次学习的书籍主要是Hands-on Machine Learning with Scikit-Learn and TensorFlow(豆瓣:https://book.douban.com ...

  5. (三)unittest断言方法的介绍

    断言如同在测试用例上,类似于预期结果与实际结果是否一致,如果一致则表示测试通过,Assert断言很好的用于测试结果判断上,更灵活的对预期结果和实际结果进行对比,下面简单的介绍一下unittest的As ...

  6. MongoDB 上手开发实践(入门上手开发这一篇就够了)

    前言 MongoDB是一个介于 关系数据库 和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.它支持的数据结构非常松散,是类似 json 的 bson 格式,因此可以存储比较复 ...

  7. poj 2689 区间素数筛

    The branch of mathematics called number theory is about properties of numbers. One of the areas that ...

  8. 一个按键搞定日常git操作

    Git is a free and open source distributed version control system designed to handle everything from ...

  9. 对标Eureka的AP一致性,Nacos如何实现Raft算法

    一.快速了解Raft算法 Raft 适用于一个管理日志一致性的协议,相比于 Paxos 协议 Raft 更易于理解和去实现它. 为了提高理解性,Raft 将一致性算法分为了几个部分,包括领导选取(le ...

  10. java jdk9的特性 jshell

    1.进入 jshell 2.推出 /exit() 和python的解释器用法差不多