• Poj1734题解


    • 题目大意
      求一个无向图的最小环

    • 题解
      假设是有向图的话。仅仅须要令f[i][i]=+,再floyd就可以;
      对无向图。应该在floyd算法循环至k的一開始进行例如以下操作:
      枚举i和j,假设点i存在经过点j的环,则用ikkjjki 的最短路去更新最小环的长度,
      ans=min{ans,map[i][k]+map[k][j]+f[i][j]}
      然后更新最小环。
      这个工作进行完之后。才干够用floyd计算ikj的最短路。

    • Code

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int oo = 1000000000;
    int n, m, map[110][110], pre[110][110], f[110][110];
    int ans, path[110], top;
    void init()
    {
        int x, y, z;
        scanf("%d%d", &n, &m);
        memset(f, -1, sizeof(f));
        memset(map, -1, sizeof(map));
        memset(pre, -1, sizeof(pre));
        for(int i = 1; i <= m; ++i)
        {
            scanf("%d%d%d", &x, &y, &z);
            if(f[x][y] == -1)
            {
                f[x][y] = f[y][x] = map[x][y] = map[y][x] = z;
            }
            else
            {
                f[x][y] = f[y][x] = map[x][y] = map[y][x] = min(map[x][y], z);
            }
            pre[x][y] = x;
            pre[y][x] = y;
        }
        for(int i = 1; i <= n; ++i)
        {
            f[i][i] = map[i][i] = 0;
        }
        ans = oo;
    }
    void work()
    {
        for(int k = 1; k <= n; ++k)
        {
            for(int i = 1; i < k; ++i)
            {
                for(int j = i + 1; j < k; ++j)
                {
                    if(map[i][k] != -1 && map[k][j] != -1 && f[i][j] != -1 && ans > f[i][j] + map[i][k] + map[k][j])
                    {
                        ans = f[i][j] + map[i][k] + map[k][j];
                        int t = j;
                        top = 0;
                        while(t != i)
                        {
                            path[++top] = t;
                            t = pre[i][t];
                        }
                        path[++top] = i;
                        path[++top] = k;
                    }
                }
            }
            //以上为找最小环
            //下面为floyd更新最短路
            for(int i = 1; i <= n; ++i)
            {
                for(int j = 1; j <= n; ++j)
                {
                    if(f[i][k] != -1 && f[k][j] != -1 && (f[i][j] == -1 || f[i][j] > f[i][k] + f[k][j]))
                    {
                        f[i][j] = f[i][k] + f[k][j];
                        pre[i][j] = pre[k][j];
                    }
                }
            }
        }
        if(ans == oo)
        {
            puts("No solution.");
            return;
        }
        for(int i = 1; i <= top; ++i) printf("%d ", path[i]);
    }
    int main()
    {
        init();
        work();
        return 0;
    }
    
  • 相关阅读:
    Ansible批量更新远程主机用户密码
    国外程序员推荐:每个程序员都应该读的非编程书
    FindFriendsServer服务搭建
    Android JNI HelloWorld实现
    2014年4月读书单
    jQuery 之父:每天写代码
    QT210 Android4.0源码编译和烧录文档整理
    Android系统分区理解及分区目录细解
    Android组件Spinner使用
    使用事件驱动模型实现高效稳定的网络服务器程序
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/7039679.html
Copyright © 2020-2023  润新知