Codeforces Round #349 (Div. 1) B. World Tour 最短路+暴力枚举

题目链接:

http://www.codeforces.com/contest/666/problem/B

题意:

给你n个城市,m条单向边,求通过最短路径访问四个不同的点能获得的最大距离,答案输出一个满足条件的四个点。

题解:

首先预处理出任意两点的最短距离,用队列优化的spfa跑:O(n*n*logn)

现依次访问四个点:v1,v2,v3,v4

我们可以枚举v2,v3,然后求出v2的最远点v1,v3的最远点v4,为了保证这四个点的不同,直接用最远点会错,v1,v4相同时还要考虑次最远点来替换,反正解肯定是在离v2最远的三个点里面,在离v3最远的三个点里面,这个可以暴力枚举(3*3)。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<vector>
  4 #include<queue>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 const int maxn = 3e3 + 10;
  9 const int INF = 0x3f3f3f3f;
 10 
 11 vector<int> G[maxn];
 12 int mat[maxn][maxn];
 13 
 14 int n, m;
 15 
 16 int dis[maxn], inq[maxn];
 17 void spfa(int s) {
 18     queue<int> Q;
 19     memset(inq, 0, sizeof(inq));
 20     for (int i = 0; i < n; i++) dis[i] = INF;
 21     dis[s] = 0; inq[s] = 1; Q.push(s);
 22     while (!Q.empty()) {
 23         int u = Q.front(); Q.pop();
 24         inq[u] = false;
 25         for (int i = 0; i < G[u].size(); i++) {
 26             int v = G[u][i];
 27             if (dis[v] > dis[u] + 1) {
 28                 dis[v] = dis[u] + 1;
 29                 if (!inq[v]) {
 30                     Q.push(v); inq[v] = true;
 31                 }
 32             }
 33         }
 34     }
 35     for (int i = 0; i < n; i++) {
 36         mat[s][i] = dis[i];
 37     }
 38 }
 39 
 40 int ma_out[maxn][3];
 41 int ma_in[maxn][3];
 42 //处理离i最远的三个顶点,要考虑两种情况,即进入i的点和从i出去的点
 43 void pre_ma() {
 44     for (int i = 0; i < n; i++) {
 45         ma_out[i][0] = ma_out[i][1] =ma_out[i][2]= -1;
 46         for (int j = 0; j < n; j++) {
 47             if (mat[i][j] >= INF) continue;
 48             if (ma_out[i][2]==-1||mat[i][ma_out[i][2]] < mat[i][j]) {
 49                 ma_out[i][0] = ma_out[i][1];
 50                 ma_out[i][1] = ma_out[i][2];
 51                 ma_out[i][2] = j;
 52             }
 53             else if (ma_out[i][1]==-1||mat[i][ma_out[i][1]] < mat[i][j]) {
 54                 ma_out[i][0] = ma_out[i][1];
 55                 ma_out[i][1] = j;
 56             }
 57             else if (ma_out[i][0]==-1||mat[i][ma_out[i][0]] < mat[i][j]) {
 58                 ma_out[i][0] = j;
 59             }
 60         }
 61     }
 62     for (int i = 0; i < n; i++) {
 63         ma_in[i][0] = ma_in[i][1] = ma_in[i][2] = -1;
 64         for (int j = 0; j < n; j++) {
 65             if (mat[j][i] >= INF) continue;
 66             if (ma_in[i][2]==-1||mat[ma_in[i][2]][i] < mat[j][i]) {
 67                 ma_in[i][0] = ma_in[i][1];
 68                 ma_in[i][1] = ma_in[i][2];
 69                 ma_in[i][2] = j;
 70             }
 71             else if (ma_in[i][1]==-1||mat[ma_in[i][1]][i] < mat[j][i]) {
 72                 ma_in[i][0] = ma_in[i][1];
 73                 ma_in[i][1] = j;
 74             }
 75             else if (ma_in[i][0]==-1||mat[ma_in[i][0]][i] < mat[j][i]) {
 76                 ma_in[i][0] = j;
 77             }
 78         }
 79     }
 80 }
 81 
 82 void init() {
 83     for (int i = 0; i < n; i++) G[i].clear();
 84 }
 85 
 86 int main() {
 87     while (scanf("%d%d", &n, &m) == 2 && n) {
 88         init();
 89         for (int i = 0; i < m; i++) {
 90             int u, v;
 91             scanf("%d%d", &u, &v); u--, v--;
 92             G[u].push_back(v);
 93         }
 94         for (int i = 0; i < n; i++) spfa(i);
 95         pre_ma();
 96         int ans = -1;
 97         int nds[4] = { 0 };
 98         //枚举中间两个点,再算旁边两个点
 99         for (int i = 0; i < n; i++) {
100             for (int j = 0; j < n; j++) {
101                 if (i == j) continue;
102                 if (mat[i][j] >= INF) continue;
103                 for (int k = 0; k < 3; k++) {
104                     for (int l = 0; l < 3; l++) {
105                         if (ma_in[i][k] == -1 || ma_out[j][l] == -1) continue;
106                         if (ma_in[i][k] == i || ma_in[i][k] == j || ma_in[i][k] == ma_out[j][l]) continue;
107                         if (ma_out[j][l] == i || ma_out[j][l] == j) continue;
108                         if (ans < mat[ma_in[i][k]][i] + mat[i][j] + mat[j][ma_out[j][l]]) {
109                             ans = mat[ma_in[i][k]][i] + mat[i][j] + mat[j][ma_out[j][l]];
110                             nds[0] = ma_in[i][k];
111                             nds[1] = i;
112                             nds[2] = j;
113                             nds[3] = ma_out[j][l];
114                         }
115                     }
116                 }
117             }
118         }
119         printf("%d %d %d %d
", nds[0] + 1, nds[1] + 1, nds[2] + 1, nds[3] + 1);
120     }
121     return 0;
122 }
原文地址:https://www.cnblogs.com/fenice/p/5518438.html