zoukankan      html  css  js  c++  java
  • Ural 1004 FLOYD最小环问题

    题目大意: 给出一些双向边, 求图中的一个最小环, 当u-v被选中时, v-u不能被选, 按顺序输出这个最小环, n<=100
    无解则输出。

    题目既然要求最小环,数据范围还这么小, 容易联想到FLOYD, 并且这里是双向边也没有什么关系, 因为只能选一条, 但题目比较麻烦的地方就是要输出这个环,

    我的处理好像和机房的人不一样。。。。。
    我想到的办法是对于每一个i -> j的路径, 记下最优的中间点, 再记下最小环中的最大序号点, 和最小环中的floyd的那一条路径的起点和终点, 递归输出。
    开始一直WA#2, 一开始以为是我的FLOYD和网上主流的FLOYD不一样, 然而好像我的FLOYD那个细节地方貌似无关紧要, 然后突然发现有个BUG!!!! 因为我的最小环记下的路径是前k-1个点为中间点更新后的答案, 所以一种诡异的情况就是第k次恰好可以更新掉我记下的路径, 那么我输出的答案会有两个k点(手动滑稽。。。。)所以我就做了两遍, 先做出最小环再跑一遍FLOYD就ok

    好像还可以用个vector来更新答案, 不过没我的方便hhhh
    贴代码-----

    #include <cstdio>
    #include <cstring>
    
    const int N = 100 + 10;
    const int oo = 1e8 + 1e7 + 7e5;
    #define min(a, b) a < b? a : b
    #define rep(i, s, t) for(int i = s; i <= t; ++i)
    
    int G[N][N], p[N], Mid, x, y, top;
    int n, m, a[N][N], f[N][N], Ans[N];
    
    void init() {
        top = 0; 
        Mid = 0, x = 0, y = 0;
        rep(i, 0, n) p[i] = 0;
        rep(i, 0, n) rep(j, 0, n) 
            a[i][j] = f[i][j] = oo, G[i][j] = 0;
    }
    
    void dfs(int i, int j) {
        if(a[i][j] == f[i][j]) {
            if(!p[i]) Ans[++top] = i, p[i] = 1;
            if(!p[j]) Ans[++top] = j, p[j] = 1;
            return ;
        }
        dfs(i, G[i][j]), dfs(G[i][j], j);
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("input.in", "r", stdin);
        freopen("res.out", "w", stdout);
    #endif
        while(1) {
            scanf("%d", &n);
            if(n == -1) break;
            scanf("%d", &m);
            init();
    
            rep(i, 1, m) {
                int u, v, w;
                scanf("%d%d%d", &u, &v, &w);
                a[u][v] = a[v][u] = min(a[u][v], w);
                f[u][v] = f[v][u] = a[u][v];
            }
            rep(i, 0, n) a[i][i] = f[i][i] = 0;
    
            int Res = oo;
            rep(k, 1, n) {
                rep(i, 1, k-1)
                    rep(j, 1, k-1)
                        if(i ^ j)
                            if(a[k][i] + a[j][k] + f[i][j] < Res)
                                Res = a[k][i] + a[j][k] + f[i][j];
                rep(i, 1, n)
                    rep(j, 1, n)
                        if(f[i][k] + f[k][j] < f[i][j]) {
                            f[i][j] = f[i][k] + f[k][j];
                            G[i][j] = k;
                        }
            }
    
            if(Res >= oo) {
                puts("No solution.");
                continue;
            }
            bool flag = 0;
            rep(i, 1, n) rep(j, 1, n) f[i][j] = a[i][j], G[i][j] = 0;
            rep(k, 1, n) {
                rep(i, 1, k-1) {
                    rep(j, 1, k-1)
                        if(i ^ j)
                            if(a[k][i] + a[j][k] + f[i][j] == Res) {
                                Mid = k, x = i, y = j;
                                flag = 1;
                                break;
                            }
                    if(flag) break;
                }
                if(flag) break;
                rep(i, 1, n)
                    rep(j, 1, n)
                        if(f[i][k] + f[k][j] < f[i][j]) {
                            f[i][j] = f[i][k] + f[k][j];
                            G[i][j] = k;
                        }
            }
    
            p[Mid] = 1, Ans[++top] = Mid;
            dfs(x, y);
            rep(i, 1, top) printf("%d%c", Ans[i], i^top? ' ':'
    ');
        }
        return 0;
    }

    看起来很长吧, 其实思路很清晰的。。。。。相信你们也不会来看我的这么丑的代码

  • 相关阅读:
    图形化编程娱乐于教,Kittenblock实例,角色对话
    图形化编程娱乐于教,Kittenblock实例,角色旋转方式
    图形化编程娱乐于教,Kittenblock实例,蝙蝠侠在宇宙中的坐标位置
    图形化编程娱乐于教,Kittenblock实例,角色移动,面向方向
    图形化编程娱乐于教,Kittenblock实例,角色移动
    图形化编程娱乐于教,Kittenblock实例,确认坐标
    图形化编程娱乐于教,Kittenblock实例,计算跑步距离
    图形化编程娱乐于教,Kittenblock实例,角色上跳效果
    图形化编程娱乐于教,Kittenblock实例,提问机器
    图形化编程娱乐于教,Kittenblock实例,数数,说出5的倍数
  • 原文地址:https://www.cnblogs.com/pbvrvnq/p/8530154.html
Copyright © 2011-2022 走看看