码迷,mamicode.com
首页 > 其他好文 > 详细

uva 1416 Warfare And Logistics (最短路树)

时间:2015-08-11 23:38:26      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:uva

uva 1416 Warfare And Logistics

Description

The army of United Nations launched a new wave of air strikes on terrorist forces. The objective of the mission is to reduce enemy’s logistical mobility. Each air strike will destroy a path and therefore increase the shipping cost of the shortest path between two enemy locations. The maximal damage is always desirable.

Let’s assume that there are n enemy locations connected by m bidirectional paths, each with specific shipping cost. Enemy’s total shipping cost is given as c = ni=1nj=1path(i, j) . Here path(i, j) is the shortest path between locations i and j . In case i and j are not connected, path(i, j) = L . Each air strike can only destroy one path. The total shipping cost after the strike is noted as c’ . In order to maximized the damage to the enemy, UN’s air force try to find the maximal c’ - c .

Input

The first line ofeach input case consists ofthree integers: n , m , and L . 1 < n100 , 1m1000 , 1L108 . Each ofthe following m lines contains three integers: a , b , s , indicating length of the path between a and b .

Output

For each case, output the total shipping cost before the air strike and the maximal total shipping cost after the strike. Output them in one line separated by a space.

Sample Input

4 6 1000
1 3 2
1 4 4
2 1 3
2 3 3
3 4 1
4 2 2

Sample Output

28 38

题目大意:给出一个n个结点m条边的无向图,每条边上有一个正权。令c等于没对节点的最短路长度之和。例如n=3时,c=d(1,1)+d(1,2)+d(1,3)+d(2,1)+d(2,2)+d(2,3)+d(3,1)+d(3,2)+d(3,3)。要求删除一条边后使得新的c值最大。不连通的两点间距离视为L。

解题思路:如果删除每一条边后求一次最短路,肯定会超时。其实有一些边,删了之后对c的值是没有影响的,这些边,就是游离在最短路之外的边。所以我们只要找出在最短路上的边,然后枚举删除这些边,就行了。最短路上的n个点,和n - 1条边构成最短路树。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
using namespace std;

const int N = 200;
const int M = 5005;
const int INF = 0x3f3f3f3f;;
typedef long long ll;
int n, m, l;
ll Dis[N];

struct Edge{  
    int from,to;  
    ll dist;  
    int flag;  
};  
struct HeapNode{
    int d,u;  
    bool operator < (const HeapNode& rhs) const{  
        return d > rhs.d;  
    }  
};  

struct Dijkstra{  
    int n,m;              //点数和边数  
    vector<Edge> edges;   //边列表  
    vector<int> G[M];     //每个结点出发的边编号(从0开始编号)  
    vector<int> tree[M];
    bool done[N];         //是否已永久标号  
    int d[N];             //s到各个点的距离  
    int p[N];             //最短路中的上一条边  
    ll L; 

    void init(int n, ll l) {  
        this->n = n;  
        for(int i = 0; i <= m * 2; i++) {
            G[i].clear();//清空邻接表  
            tree[i].clear();
        }
        memset(p, -1, sizeof(p));
        edges.clear();//清空边表  
        this->L = l;
    }  

    void addEdge(int from, int to, ll dist, int flag) {   
        //如果是无向图,每条无向边需调用两次AddEdge  
        edges.push_back((Edge){from, to, dist, flag});  
        m = edges.size();  
        G[from].push_back(m - 1);  
    }  

    ll dijkstra(int s) {//求s到所有点的距离  
        priority_queue<HeapNode> Q;  
        for(int i = 0; i <= n; i++) d[i] = INF;  
        d[s] = 0;  
        memset(done, 0, sizeof(done));  
        Q.push((HeapNode){0, s});  
        while(!Q.empty()){  
            HeapNode x = Q.top(); Q.pop();  
            int u = x.u;  
            if(done[u]) continue;  
            done[u] = true;  
            for(int i = 0; i < G[u].size(); i++){  
                Edge& e = edges[G[u][i]];  
                if(!e.flag) continue;  
                if(d[e.to] > d[u] + e.dist){  
                    d[e.to] = d[u] + e.dist;  
                    p[e.to] = G[u][i]; 
                    Q.push((HeapNode){d[e.to], e.to});  
                }  
            }  
        }  
        ll ans = 0;
        for (int i = 1; i <= n; i++) {
            if (i == s) continue;   
            if (d[i] == INF) ans += L;
            else ans += d[i];
        }
        return ans;
    }  

    void getTree(int s) {
        for (int i = 1; i <= n; i++)    {
            if (i == s || p[i] == -1) continue; 
            tree[p[i]].push_back(s);
        }
    }

    void deleteEdge(int x) {
        edges[x].flag = 0;  
        edges[x^1].flag = 0;
    }

    void recoverEdge(int x) {
        edges[x].flag = 1;
        edges[x^1].flag = 1;
    }
}dij;  

void input() {
    int u, v;
    ll dis;
    for (int i = 0; i < m; i++) {
        scanf("%d %d %lld", &u, &v, &dis);  
        if (u == v) continue;
        dij.addEdge(u, v, dis, 1);
        dij.addEdge(v, u, dis, 1);
    }
}

void solve() {
    ll ans1 = 0, ans2, temp;
    for (int i = 1; i <= n; i++) {
        Dis[i] = dij.dijkstra(i);
        ans1 += Dis[i]; 
        dij.getTree(i);
    }
    ans2 = ans1;
    for (int i = 0; i < dij.edges.size(); i++) {
        dij.deleteEdge(i);
        if (i % 2 == 0) temp = ans1;    
        for (int j = 0; j < dij.tree[i].size(); j++) {
            temp -= Dis[dij.tree[i][j]];    
            temp += dij.dijkstra(dij.tree[i][j]);
        }
        dij.recoverEdge(i);
        ans2 = max(ans2, temp);
    }
    printf("%lld %lld\n", ans1, ans2);
}

int main() {
    while (scanf("%d %d %d", &n, &m, &l) == 3) {
        dij.init(n, l);
        input();    
        solve();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不可转载。

uva 1416 Warfare And Logistics (最短路树)

标签:uva

原文地址:http://blog.csdn.net/llx523113241/article/details/47427149

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!