uva1416 dijkstra

大白书P330 这题比较麻烦

给出一个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值c‘最大。不连通的两点的最短路径长度为L

// LA4080/UVa1416 Warfare And Logistics
// Rujia Liu
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;

const int INF = 1000000000;
const int maxn = 100 + 10;

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 d[maxn];        // s到各个点的距离
  int p[maxn];        // 最短路中的上一条弧

  void init(int n) {
    this->n = n;
    for(int i = 0; i < n; i++) G[i].clear();
    edges.clear();
  }

  void AddEdge(int from, int to, int dist) {
    edges.push_back((Edge){from, to, dist});
    m = edges.size();
    G[from].push_back(m-1);
  }

  void dijkstra(int 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.dist > 0 && d[e.to] > d[u] + e.dist) { // 此处和模板不同,忽略了dist=-1的边。此为删除标记。根据题意和dijkstra算法的前提,正常的边dist>0
          d[e.to] = d[u] + e.dist;
          p[e.to] = G[u][i];
          Q.push((HeapNode){d[e.to], e.to});
        }
      }
    }
  }
};

//////// 题目相关
Dijkstra solver;
int n, m, L;
vector<int> gr[maxn][maxn]; // 两点之间的原始边权
int used[maxn][maxn][maxn]; // used[src][a][b]表示源点为src的最短路树是否包含边a->b
int idx[maxn][maxn]; // idx[u][v]为边u->v在Dijkstra求解器中的编号
int sum_single[maxn]; // sum_single[src]表示源点为src的最短路树的所有d之和

int compute_c() {
  int ans = 0;
  memset(used, 0, sizeof(used));
  for(int src = 0; src < n; src++) {
    solver.dijkstra(src);
    sum_single[src] = 0;
    for(int i = 0; i < n; i++) {
      if(i != src) {
        int fa = solver.edges[solver.p[i]].from;
        used[src][fa][i] = used[src][i][fa] = 1;
      }
      sum_single[src] += (solver.d[i] == INF ? L : solver.d[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 {
      solver.dijkstra(src);
      for(int i = 0; i < n; i++)
        ans += (solver.d[i] == INF ? L : solver.d[i]);
    }
  return ans;
}

int main() {
  while(scanf("%d%d%d", &n, &m, &L) == 3) {
    solver.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++) {
      int a, b, s;
      scanf("%d%d%d", &a, &b, &s); a--; b--;
      gr[a][b].push_back(s);
      gr[b][a].push_back(s);
    }

    // 构造网络
    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());
        solver.AddEdge(i, j, gr[i][j][0]);
        idx[i][j] = solver.m - 1;
        solver.AddEdge(j, i, gr[i][j][0]);
        idx[j][i] = solver.m - 1;
      }

    int c = compute_c();
    int c2 = -1;
    for(int i = 0; i < n; i++)
      for(int j = i+1; j < n; j++) if(!gr[i][j].empty()) {
        int& e1 = solver.edges[idx[i][j]].dist;
        int& e2 = solver.edges[idx[j][i]].dist;
        if(gr[i][j].size() == 1) e1 = e2 = -1;
        else e1 = e2 = gr[i][j][1]; // 大二短边
        c2 = max(c2, compute_newc(i, j));
        e1 = e2 = gr[i][j][0]; // 恢复
      }

    printf("%d %d\n", c, c2);
  }
  return 0;
}

时间: 2024-11-07 00:06:06

uva1416 dijkstra的相关文章

畅通project续HDU杭电1874【dijkstra算法 || SPFA】

http://acm.hdu.edu.cn/showproblem.php?pid=1874 Problem Description 某省自从实行了非常多年的畅通project计划后.最终修建了非常多路.只是路多了也不好,每次要从一个城镇到还有一个城镇时,都有很多种道路方案能够选择,而某些方案要比还有一些方案行走的距离要短非常多.这让行人非常困扰. 如今,已知起点和终点,请你计算出要从起点到终点.最短须要行走多少距离. Input 本题目包括多组数据.请处理到文件结束. 每组数据第一行包括两个正

Choose the best route 【Dijkstra】

Problem DescriptionOne day , Kiki wants to visit one of her friends. As she is liable to carsickness , she wants to arrive at her friend's home as soon as possible . Now give you a map of the city's traffic route, and the stations which are near Kiki

Bus System 【dijkstra算法】

Because of the huge population of China, public transportation is very important. Bus is an important transportation method in traditional public transportation system. And it's still playing an important role even now.The bus system of City X is qui

Dijkstra

//在这里采用两种方式实现Dijkstra算法,经过测试两种方式:第一种:通过Dist[]让每一个顶点中Dist[]中寻找最短路径的点:第二种方式:从已经收录的顶点的相邻顶点中选择出最短路//径的的顶点,此种方式适合用于稠密图,减少点的遍历. #include<iostream> #include<malloc.h> using namespace std; #define INF (100000) //相连顶点的信息 typedef struct AdjNode{ int Wei

ACM: HDU 2544 最短路-Dijkstra算法

HDU 2544最短路 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据.每组数据第一行是两个整数N.M(N<=100,M<

ACM: HDU 3790 最短路径问题-Dijkstra算法

HDU 3790 最短路径问题 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. Input 输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p.最后一行是

dijkstra堆优化模板

1 #include<iostream> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<queue> 7 #define inf 2147483647 8 using namespace std; 9 struct data 10 { 11 int from,to,next,w; 12 data(){f

邻接表实现Dijkstra算法以及DFS与BFS算法

//============================================================================ // Name : ListDijkstra.cpp // Author : fffff // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //==========================

Dijkstra算法(求解单源最短路)详解 + 变形 之 poj 1860 Currency Exchange

/* 求解单源最短路问题:Dijkstra算法(该图所有边的权值非负) 关键(贪心): (1)找到最短距离已经确定的节点,从它出发更新与其相邻节点的最短距离: (2)此后不再关心(1)中“最短距离已经确定的节点”. 时间复杂度(大概的分析,不准确): “找到最短距离已经确定的节点” => O(|V|) "从它出发更新与其相邻节点的最短距离" => 邻接矩阵:O(|V|),邻接表:O(|E|) 需要循环以上两个步骤V次,所以时间复杂度:O(V^2) 即:在|E|较小的情况下,