La 4080 Warfare and logistics Dijkstra

来源:互联网 发布:阿里旅行软件 编辑:程序博客网 时间:2024/06/05 09:57

题目大意:
给定n个点,m条边的无向图, 定义c为任意两点间的最短路之和,

c=w(i,j)|iV,jV

求初始时的c与删去任意一条边后的c’的最大值。
分析:
对于最初始时的c, 我们可以通过每次计算以某个点为源点的最短路径,不难发现,每次计算后的距离和就是初始值c。
每一次进行删边操作时,就可以枚举每一条边进行决策:删除或者不删除,对于删除的边,如果它不在以某个点为源点的Dijkstra树上,那么删除它对于最短路径的长度就不会造成影响,所以我们可以忽略它,直接利用上一次计算初始c值时的答案即可。这样可以使时间复杂度变得可以令人接受。
代码:

#include<bits/stdc++.h>using namespace std;const int maxn = 100 + 10;const int inf = 0x7fffffff;struct edge { int from, to, dist; };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[maxn];    bool done[maxn];    int dis[maxn], pre[maxn];    void init(int n) {        this->n = n;        for(int i=0; i<n; i++) G[i].clear();        edges.clear();    }    void add_edge(int from, int to, int dist) {        edges.push_back((edge){from, to, dist});        m = edges.size();        G[from].push_back(m-1);    }    //get the single-source shortest path from s    void dijkstra(int s) {        priority_queue<Heapnode> q;        for(int i=0; i<n; i++) dis[i] = inf; dis[s] = 0;        memset(done, false, 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<(int)G[u].size(); i++) {                edge& e = edges[G[u][i]];                if(e.dist > 0 && dis[e.to] > dis[u] + e.dist) {                    dis[e.to] = dis[u] + e.dist;                    pre[e.to] = G[u][i];                    q.push((Heapnode){dis[e.to], e.to});                }            }        }    }}Dij;int n, m, L, u, v, w;vector<int> gr[maxn][maxn];bool used[maxn][maxn][maxn]; // in the shortest path from src, the edge u->v wheather or not usedint idx[maxn][maxn]; //the number in the Dij structureint sum_single[maxn];int compute_c() {    int ans = 0;    memset(used, false, sizeof(used));    for(int src=0; src < n; src++) {        Dij.dijkstra(src);        sum_single[src] = 0;        for(int i=0; i<n; i++) {            if(i != src) {                int fa = Dij.edges[Dij.pre[i]].from;                used[src][i][fa] = used[src][fa][i] = 1;            }sum_single[src] += Dij.dis[i] == inf ? L : Dij.dis[i];        }ans += sum_single[src];    }    return ans;}int compute_newc(int a, int b) {     int ans = 0;    for(int src=0; src < n; src++) {        if(!used[src][a][b]) ans += sum_single[src];        else {            Dij.dijkstra(src);            for(int i=0; i<n; i++)                 ans += Dij.dis[i] == inf ? L : Dij.dis[i];        }    }    return ans;}int main() {#ifndef ONLINE_JUDGE     freopen("data.txt", "r", stdin);    freopen("ans.txt", "w", stdout);#endif    while(scanf("%d%d%d", &n, &m, &L) == 3 && n) {        Dij.init(n);        for(int i=0; i<n; i++)             for(int j=0; j<n; j++)                 gr[i][j].clear();        for(int i=0; i<m; i++) {            scanf("%d%d%d", &u, &v, &w); u--, v--;            gr[u][v].push_back(w);            gr[v][u].push_back(w);        }        for(int i=0; i<n; i++)             for(int j=i+1; j<n; j++) if(!gr[i][j].empty()) {                sort(gr[i][j].begin(), gr[i][j].end());                Dij.add_edge(i, j, gr[i][j][0]);                idx[i][j] = Dij.m - 1;                Dij.add_edge(j, i, gr[i][j][0]);                idx[j][i] = Dij.m - 1;            }        int c = compute_c();        int c1 = -1;        for(int i=0; i<n; i++)             for(int j=i+1; j<n; j++) if(!gr[i][j].empty()) {                int& e1 = Dij.edges[idx[i][j]].dist;                int& e2 = Dij.edges[idx[j][i]].dist;                if(gr[i][j].size() == 1) e1 = e2 = -1;                else e1 = e2 = gr[i][j][1];                c1 = max(c1, compute_newc(i, j));                e1 = e2 = gr[i][j][0];            }        printf("%d %d\n", c, c1);    }    return 0;}
0 0
原创粉丝点击