• HDU2433 最短路 + 剪枝优化


      题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2433 ,最短路(SPFA或优化过的Dijstra) + 剪枝优化

      这道题关键还是在几个剪枝上面,没有剪枝会TLE。


    先说下几个数组的意义:

      a[]存储M条边的信息;vis[i]表示点i是否访问过;path[i][u][v]表示在点i的所有最短路里,边u - v是否属于某条最短路;cnt[u][v]表示边u - v出现的次数;pos[u][i]表示第i条边在邻接表e[u]中的位置;sum[i]表示预处理时顶点i到所有顶点的最短路的和;dist[i]表示顶点i到其他顶点的最短路的距离;e[i]即邻接表,存储与顶点i邻接的点的信息。

    算法:

      先预处理一遍,求得每个顶点的最短路,并存在sum[i]中,如果预处理时发现图不连通,则M次询问都输出"INF";

      处理第i条边的时候,如果这条边出现不止一次,即 cnt[u][v] > 1,这时候除掉这条边后不影响结果,输出预处理的结果即可;

      如果不满足上述条件,就开始求n个顶点的最短路情况:求顶点i的最短路的时候,如果边u - v不在顶点i的最短路中,即 path[i][u][v] == 0时,这时候这条边除掉不影响顶点i的最短路的结果,所以仍为sum[i];如果出现去掉这条边图不连通的情况,这次询问输出"INF"。

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <string>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define LL __int64
    #define eps 1e-8
    #define INF 1e8
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int MOD = 2333333; 
    const int maxn = 100 + 5;
    const int N = 3000 + 5;
    struct Edge {
        int v , w;
        bool operator < (const Edge &tmp) const {
            return w > tmp.w;
        }
    } a[N];
    bool vis[maxn] , path[maxn][maxn][maxn];
    int cnt[maxn][maxn] , pos[maxn][N];
    int sum[maxn] , dist[maxn];
    vector <Edge> e[maxn];
    
    int Dijstra(int s , int n , bool ch)    //Dijstra + 优先队列
    {        //ch表示是否为预处理,因为在预处理的时候才需要判断path[i][u][v]的情况
        memset(vis , 0 , sizeof(vis));
        for(int i = 1 ; i <= n ; i++)
            dist[i] = INF;
        dist[s] = 0;
        priority_queue <Edge> que;
        Edge tmp = {s , 0};
        que.push(tmp);
        while(!que.empty()) {
            Edge u = que.top();
            que.pop();
            if(vis[u.v])
                continue;
            vis[u.v] = 1;
            for(int i = 0 ; i < e[u.v].size() ; i++) {
                int j = e[u.v][i].v;
                if(dist[j] > dist[u.v] + e[u.v][i].w) {
                    dist[j] = dist[u.v] + e[u.v][i].w;
                    if(!vis[j]) {
                        if(ch)    //这条边在最短路中
                            path[s][u.v][j] = path[s][j][u.v] = 1;
                        que.push(e[u.v][i]);
                    }
                }
            }
        }
        int ans = 0;
        for(int i = 1 ; i <= n ; i++) {
            if(dist[i] >= INF)
                return INF;
            ans += dist[i];
        }
        return ans;
    }
    int main()
    {
        int n , m , u , v , i , ans;
        while(~scanf("%d %d" , &n , &m))
        {
            memset(path , 0 , sizeof(path));
            memset(cnt , 0 , sizeof(cnt));
            for(i = 1 ; i <= n ; i++)
                e[i].clear();
            for(i = 1 ; i <= m ; i++) {
                scanf("%d %d" , &u , &v);
                Edge tmp = {v , 1};
                e[u].push_back(tmp);
                tmp.v = u;
                e[v].push_back(tmp);
                pos[u][i] = e[u].size() - 1;
                pos[v][i] = e[v].size() - 1;
                cnt[u][v]++;
                cnt[v][u]++;
                a[i].v = u;
                a[i].w = v;
            }
            bool flag = false;
            for(i = 1 , ans = 0 ; i <= n ; i++) {
                sum[i] = Dijstra(i , n , 1);
                if(sum[i] == INF) {
                    flag = true;
                    break;
                }
                ans += sum[i];
            }
            for(i = 1 ; i <= m ; i++) {
                u = a[i].v;
                v = a[i].w;
                if(flag) {
                    puts("INF");
                } else if(cnt[u][v] > 1) {
                    printf("%d
    " , ans);
                } else {
                    int tmp , res;
                    res = ans;
                    e[u][pos[u][i]].w = INF;    //删掉第i条边
                    e[v][pos[v][i]].w = INF;
                    for(int j = 1 ; j <= n ; j++) {
                        if(path[j][u][v]) {
                            tmp = Dijstra(j , n , 0);
                            if(tmp == INF) {
                                puts("INF");
                                break;
                            }
                            res += tmp - sum[j];
                        }
                    }
                    if(tmp != INF)
                        printf("%d
    " , res);
                    e[u][pos[u][i]].w = 1;        //还原这条边
                    e[v][pos[v][i]].w = 1;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    每天一个css text-indent
    每天一个css word-break word-wrap white-space
    [转载]CentOS+nginx+uwsgi+Python+django 环境搭建
    【转】django使用model创建数据库表使用的字段
    Django对mysql操作
    mysql增删改查
    mysql用户管理
    centos7启动mysql
    centos安装python3
    [转载]python学习目录(转至袁先生的博客)
  • 原文地址:https://www.cnblogs.com/H-Vking/p/4321513.html
Copyright © 2020-2023  润新知