FZU 2090 旅行社的烦恼 floyd 求无向图最小环

题目链接:旅行社的烦恼

题意是求无向图的最小环,如果有的话,输出个数,并且输出权值。

刚刚补了一发floyd 动态规划原理,用了滑动数组的思想。所以,这个题就是floyd思想的变形。在k从1到n的过程中更新到k时,mindis数组中保存的是只经过1~k-1序号的点时,任意两个之间的最短路权值,这时候,选择点k作为环的起点即终点,在[1, k)之间选择两个点i, j 得到一个环,环的权值即为mindis[i][j] + dis[i][k] + dis[j][k]。这样遍历得到的是就是所有的环,且环内不出现重复的点。环也不会重复。好巧妙~~献上我的膝盖...

附代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#define inf 100000000
using namespace std;

int dis[110][110];
int mindis[110][110];

int main() {
    int t;
    cin >> t;
    while(t--) {
        int n, m;
        cin >> n >> m;

        for (int i=1; i<=n; ++i) {
            for (int j=1; j<=n; ++j) {
                dis[i][j] = inf;
            }
        }

        for (int i=0; i<m; ++i) {
            int x, y, w;
            cin >> x >> y >> w;
            if (dis[x][y] > w) {
                dis[x][y] = w;
                dis[y][x] = w;
            }
        }

        for (int i=1; i<=n; ++i) {
            for (int j=1; j<=n; ++j) {
                mindis[i][j] = dis[i][j];
            }
        }

        int ansdis = inf, anscnt = 0;

        for (int k=1; k<=n; ++k) {
            for (int i=1; i<k; ++i) {
                for (int j=i+1; j<k; ++j) {
                    if (ansdis > dis[i][k] + dis[j][k] + mindis[i][j]) {
                        ansdis = dis[i][k] + dis[j][k] + mindis[i][j];
                        anscnt = 1;
                    }
                    else if (ansdis == dis[i][k] + dis[j][k] + mindis[i][j]) {
                        anscnt++;
                    }
                }
            }
            for (int i=1; i<=n; ++i) {
                for (int j=1; j<=n; ++j) {
                    mindis[i][j] = min(mindis[i][j], mindis[i][k] + mindis[j][k]); // 感觉最后一个mindis[j][k] 如果换成mindis[k][j]的话应该WA的,然而并没有。好奇怪...
                }
            }
        }

        if (anscnt == 0) {
            cout << "-1\n";
        }
        else cout << ansdis << " " << anscnt << endl;
    }
    return 0;
}

注释处...mindis[j][k]应该是不等于mindis[k][j]的..不解...................

时间: 2024-10-13 04:43:09

FZU 2090 旅行社的烦恼 floyd 求无向图最小环的相关文章

bzoj 1027 floyd求有向图最小环

结合得好巧妙.... 化简后的问题是: 给你两个点集A,B,求B的一个子集BB,使得BB的凸包包含A的凸包,求BB的最小大小. 先特判答案为1,2的情况,答案为3的情况,我们先构造一个有向图: 对于B集合中的两个点u,v,如果 所有A集合的点都在u->v的左侧,那么就连一条u->v的边. 于是我们可以证明一个包含A的凸包和我们连出来的有向图中的环一一对应(不考虑点数小于等于2的情况). 于是现在我们的问题就是求最小的一个环,用floyd搞,最后统计min(f[i][i]). 1 /******

多源最短路径Floyd、Floyd求最小环【模板】

Floyd算法:用来找出每对点之间的最短距离.图可以是无向图,也可以是有向图,边权可为正,也可以为负,唯一要求是不能有负环. 1.初始化:将Map[][]中的数据复制到Dist[][]中作为每对顶点之间的最短路径的初值,Pre[i][j] = i 表示 i 到 j 路径中 j 的前一节点. 2. k 从 1 到 N 循环 N 次,每次循环中,枚举图中不同的两点 i,j,如果Dist[i][j] > Dist[i][k] + Dist[k][j],则更新Dist[i][j] = Dist[i][k

HDU - 1599 find the mincost route(Floyd求最小环)

find the mincost route Time Limit: 2000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u Submit Status Description 杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个

求无向图最小割

先解释下名词的意思. 无向图的割:就是去掉一些边,使得原图不连通,最小割就是要去掉边的数量最小. 解决这个问题的常用办法就是Stoer-Wagner 算法: 先说下这个算法的步骤后面给出证明: 1.min=MAXINT,固定一个顶点P 2.从点P用类似prim的s算法扩展出"最大生成树",记录最后扩展的顶点和最后扩展的边 3.计算最后扩展到的顶点的切割值(即与此顶点相连的所有边权和),若比min小更新min 4.合并最后扩展的那条边的两个端点为一个顶点 5.转到2,合并N-1次后结束

【BZOJ 1027】 (凸包+floyd求最小环)

[题意] 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金的铁铝锡比重为用户所需要的比重. 现在,用户给出了n种他们需要的合金,以及每种合金中铁铝锡的比重.公司希望能够订购最少种类的原材料,并且使用这些原材料可以加工出用户需要的所有种类的合金. [分析] 只要考虑前两个物质的比例,因为加起来等于1. 如果你看过zoj3154,就会知道这题的模型,用二元组表

洛谷P1141 //bfs求无向图的子连通块大小(多次询问)

http://www.luogu.org/problem/show?pid=1141 多询问题,求无向图的子连通块大小. 直接bfs,读一个搜一个,过60: 100%的点1,000,000个点,100,000次询问,显然是记忆化. 我很弱,最开始开了个数组记录每个点属于的连通块的第一个点的坐标,然后写了一堆,自己都烦. 后来问某大神,似拨开云雾见到了青天.用cnt记录连通块的" 名字 ". 学会了这一招,不代表过了. 我还是读一个点,如果访问过就输出,没访问就dfs,然后每dfs就循环

World Finals 1996 Uva (Floyd求闭包)

思路:用Floyd求传递闭包. 附:逗号后的空格没看到,WA了好多次…….还有就是强连通分量也可以做,但是对这个题来说太麻烦,而且不方便输出,. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> using namespace std; int n,m; map<string,int> ma; map&l

Poj 2263 Heavy Cargo Floyd 求最大容量路

f[i][j] = max(f[i][j],min(f[i][k],f[j][k])) #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cst

zoj3080 ChiBi --- floyd求连通块内最短路

此题最大最小搞的太复杂...并查集维护连通块,连通块内floyd就可以了 #include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #