您的位置:首页 > 编程语言 > C语言/C++

La 4080 Warfare and logistics Dijkstra

2016-07-21 21:01 399 查看
题目大意:

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

即 c=∑w(i,j)|i∈V,j∈V

求初始时的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 used
int idx[maxn][maxn]; //the number in the Dij structure
int 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

a92d
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 dijkstra