数据结构 校园导游程序 (Floyd)

Description

给定用无向网表示你所在学校的校园景点平面图(图中顶点表示主要景点,存放景点的编号、名称、简介等信息,图中的边表示景点间的道路,存放路径长度等信息)。要求能够回答有关景点介绍、游览路径等问题。

Input

输入第一行为测试数据组数。每组数据第一行为3个整数n(2<=n<=200)、m(0<=m<=300)、k(0<=k<=1000),分别代表景点数、道路数和操作数。接下来1行n个整数p(1<=p<=100)代表每个景点好玩程度,景点编号从1开始。在接下来有m行,每行3个整数分别代表起点、终点、长度l(1<=l<=100)。然后k行,第一个整数q为操作类型,有如下几种输入:
0 x h:将x和与x直接连通的景点的好玩度提高h(1<=h<=100)。
1 x:查询景点x的好玩度。
2 x y l:在x和y之间建立了一条长度为l(1<=l<=100)的通路。(输入保证建立道路的次数不超过10次)。
3 x y:查询x到y的最短路的距离,不连通输出“No such path.”。

Output

对于q为1和q为3的查询,每个查询输出一行,格式见样例。

Sample Input

1
5 3 5
75 34 22 83 77
1 3 40
4 5 9
5 2 52
1 5
0 4 2
3 1 4
2 3 5 77
3 1 4

Sample Output

Case #1:
5 : 77
No such path.
1 -> 4 : 126

HINT

考察知识点:图的遍历、最短路径算法、图的修改等,时间复杂度O(n3)


Append Code

析:要最短路径么,我们可以用Floyd来最最短长度,然后在加边时,也要再用这个算法,不断更新,这个好多坑,主要的就是可能有重复边,还有同一条边可能有多个权值,

我们要选最优的,不要重复加边。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#define debug puts("+++++")
//#include <tr1/unordered_map>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;
//using namespace std :: tr1;
 
typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const LL LNF = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 200 + 5;
const LL mod = 1e3 + 7;
const int N = 1e6 + 5;
const int dr[] = {-1, 0, 1, 0, 1, 1, -1, -1};
const int dc[] = {0, 1, 0, -1, 1, -1, 1, -1};
const char *Hex[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
inline LL gcd(LL a, LL b){  return b == 0 ? a : gcd(b, a%b); }
inline int gcd(int a, int b){  return b == 0 ? a : gcd(b, a%b); }
inline int lcm(int a, int b){  return a * b / gcd(a, b); }
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
    return r >= 0 && r < n && c >= 0 && c < m;
}
set<int> sets[maxn];
set<int>::iterator it;
int dp[maxn][maxn];
int a[maxn];
 
int main() {
    int T;  cin >> T;
    int q;
    for(int kase = 1; kase <= T; ++kase){
        scanf("%d %d %d", &n, &m, &q);
        //for(int i = 1; i <= n; ++i) G[i].clear();
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                dp[i][j] = INF;
        for(int i = 1; i <= n; ++i) scanf("%d", a + i), sets[i].clear(), sets[i].insert(i);
        int u, v, c;
        for(int i = 0; i < m; ++i) {
            scanf("%d %d %d", &u, &v, &c);
            sets[u].insert(v); sets[v].insert(u);
            if (dp[u][v] > c) dp[u][v] = dp[v][u] = c;
        }
        for(int k = 1; k <= n; ++k)
            for (int i = 1; i <= n; ++i)
                for (int j = 1; j <= n; ++j)
                    if (dp[i][j] > dp[i][k] + dp[k][j])
                        dp[i][j] = dp[i][k] + dp[k][j];
 
        printf("Case #%d:
", kase);
        int x;
        for (int p = 0; p < q; ++p) {
            scanf("%d", &x);
            if (!x){
                scanf("%d %d", &u, &v);
                for (it = sets[u].begin(); it != sets[u].end(); ++it) a[(*it)] += v;
            }
            else if(x == 1) {
                scanf("%d", &u);
                printf("%d : %d
", u, a[u]);
            }
            else if(x == 2) {
                scanf("%d %d %d", &u, &v, &c);
                sets[u].insert(v); sets[v].insert(u);
                if(dp[u][v] <= c)  continue;
                dp[u][v] = dp[v][u] = c;
                for(int i = 1; i <= n; ++i)
                    for(int j = 1; j <= n; ++j)
                        if (dp[i][j] > dp[i][u] + dp[u][j])
                            dp[i][j] = dp[i][u] + dp[u][j];
 
                for(int i = 1; i <= n; ++i)
                    for(int j = 1; j <= n; ++j)
                        if (dp[i][j] > dp[i][v] + dp[v][j])
                            dp[i][j] = dp[i][v] + dp[v][j];
 
            }
            else if(x == 3) {
                scanf("%d %d", &u, &v);
                if (dp[u][v] == INF) printf("No such path.
");
                else printf("%d -> %d : %d
", u, v, dp[u][v]);
            }
        }
    }
 
    return 0;
}
原文地址:https://www.cnblogs.com/dwtfukgv/p/5990819.html