1. 程式人生 > >兩道最短路裸題(HDU 2544 最短路 / HDU 1596 find the safest road)

兩道最短路裸題(HDU 2544 最短路 / HDU 1596 find the safest road)

題意:給出n個點,m條邊的圖,求1n的 最短路。

程式碼:

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <queue>
#include <iostream>

using namespace std;

const int M = 1e5 + 10;
const int N = 1e2 + 10;
const int INF = 0x3f3f3f3f;

struct Node {
  int
p, dis; Node() {} Node(int a, int b) { p = a; dis = b; } friend bool operator < (Node a, Node b) { return a.dis > b.dis; } }; int x[M], y[M], z[M]; int edge[N][N]; int d[N]; int ct[N]; bool inq[N]; int n, m; int dij() { priority_queue<Node> q; q.push(Node(1
, 0)); d[1] = 0; while (!q.empty()) { Node f = q.top(); q.pop(); for (int i = 1; i <= n; i++) { if (d[i] > edge[f.p][i] + f.dis) { d[i] = edge[f.p][i] + f.dis; q.push(Node(i, d[i])); } } } return d[n]; } int bf() { d[1] = 0; for (int i = 0; i < n; i++) { for
(int j = 0; j < 2 * m; j++) { int a = x[j], b = y[j], c = z[j]; d[a] = min(d[a], d[b] + c); } } return d[n]; } int floyd() { for (int i = 1; i <= n; i++) edge[i][i] = 0; for (int k = 1; k <= n; k++) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { edge[i][j] = min(edge[i][j], edge[i][k] + edge[k][j]); } } } return edge[1][n]; } int spfa() { queue<int> q; q.push(1); d[1] = 0; inq[1] = true; ct[1] = 1; while (!q.empty()) { int u = q.front(); q.pop(); inq[u] = false; for (int i = 1; i <= n; i++) { if (d[i] > d[u] + edge[u][i]) { d[i] = d[u] + edge[u][i]; if (!inq[i]) { q.push(i); inq[i] = true; ct[i]++; if (ct[i] == n) return -1; } } } } return d[n]; } int main() { while (scanf("%d%d", &n, &m) != EOF) { if (!n && !m) break; memset(edge, INF, sizeof(edge)); memset(d, INF, sizeof(d)); memset(inq, false, sizeof(inq)); memset(ct, 0, sizeof(ct)); for (int i = 0; i < m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); edge[u][v] = min(edge[u][v], w); edge[v][u] = min(edge[v][u], w); x[2 * i] = u, y[2 * i] = v, z[2 * i] = w; x[2 * i + 1] = v, y[2 * i + 1] = u, z[2 * i + 1] = w; } // printf("%d\n", dij()); // printf("%d\n", bf()); // printf("%d\n", spfa()); printf("%d\n", floyd()); } return 0; }

題意:給出n個點的圖,邊以鄰接矩陣的形式給出,q組查詢,每次查詢從uv的最大安全係數。邊的安全係數之間為相乘的形式。

程式碼:

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <queue>
#include <iostream>

using namespace std;

const int N = 1e3 + 10;
const double EPS = 1e-5;

struct Node {
  int p;
  double safe;

  Node() {}

  Node(int a, double b) {
    p = a;
    safe = b;
  }

  friend bool operator < (Node a, Node b) {
    return a.safe < b.safe;
  }
};

double edge[N][N];
double d[N][N];
bool vis[N];
int n, q;

void dij(int s) {
  priority_queue<Node> q;
  q.push(Node(s, 1));
  d[s][s] = 1;
  while (!q.empty()) {
    Node now = q.top();
    q.pop();
    for (int i = 1; i <= n; i++) {
      if (d[s][i] < now.safe * edge[now.p][i]) {
        d[s][i] = now.safe * edge[now.p][i];
        q.push(Node(i, d[s][i]));
      }
    }
  }
}

int main() {
  while (scanf("%d", &n) != EOF) {
    memset(vis, false, sizeof(vis));
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= n; j++) {
        scanf("%lf", &edge[i][j]);
        d[i][j] = 0;
      }
    }
    scanf("%d", &q);
    for (int i = 1; i <= q; i++) {
      int u, v;
      scanf("%d%d", &u, &v);
      if (!vis[u]) {
        vis[u] = true;
        dij(u);
      }
      if (d[u][v] != 0)
        printf("%.3lf\n", d[u][v]);
      else
        printf("What a pity!\n");
    }
  }
  return 0;
}