zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    POJ 1328 Radar Installation
    POJ 1700 Crossing River
    POJ 1700 Crossing River
    poj 3253 Fence Repair (贪心,优先队列)
    poj 3253 Fence Repair (贪心,优先队列)
    poj 3069 Saruman's Army(贪心)
    poj 3069 Saruman's Army(贪心)
    Redis 笔记与总结2 String 类型和 Hash 类型
    数据分析方法有哪些_数据分析方法
    数据分析方法有哪些_数据分析方法
  • 原文地址:https://www.cnblogs.com/H-Vking/p/4321513.html
Copyright © 2011-2022 走看看