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;
}
原文地址:https://www.cnblogs.com/H-Vking/p/4321513.html