CF #349 div1 B. World Tour

题目链接:http://codeforces.com/problemset/problem/666/B

大意是给一张有向图,选取四个点,使得走这四个点,任意两个点之间走最短路,总距离最长。

 

3000个点直接floyd肯定不行,但是注意到任意每条路距离都是1,其实可以枚举所有源点作bfs,求出距离数组。

然后对于每个点求出以这个点为入点和出点距离最大的3个点。再根据这个信息,枚举四个点中的中间两个,再枚举这两个点距离他们最远的那3*3种情况,判断是否有重复,没有重复的话,更新答案。

  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4 #include <string>
  5 #include <cstring>
  6 #include <cstdio>
  7 #include <math.h>
  8 #include <queue>
  9 #include <stack>
 10 #include <map>
 11 #include <set>
 12 using namespace std;
 13 
 14 
 15 const int N=3005;
 16 
 17 vector<int>edge[N];
 18 int dis[N][N];
 19 int n;
 20 void bfs(int s) {
 21     queue< pair<int,int> >que;
 22     que.push(make_pair(s,0));
 23     dis[s][s]=0;
 24     while (!que.empty()) {
 25         pair<int,int> now=que.front();
 26         que.pop();
 27         int u=now.first,d=now.second;
 28         for (int i=0;i<edge[u].size();i++) {
 29             int v=edge[u][i];
 30             if (dis[s][v]>=0) continue;
 31             dis[s][v]=d+1;
 32             que.push(make_pair(v,d+1));
 33         }
 34     }
 35 }
 36 pair<int,int> in[N][3],out[N][3];
 37 void upd(pair<int,int> x,pair<int,int> *y) {
 38     for (int i=0;i<3;i++) {
 39         if (x>y[i]) {
 40             for (int j=2;j>i;j--) {
 41                 y[j]=y[j-1];
 42             }
 43             y[i]=x;
 44             break;
 45         }
 46     }
 47 }
 48 void solve() {
 49     memset(dis,-1,sizeof dis);
 50     for (int i=1;i<=n;i++){
 51         bfs(i);
 52         for (int j=0;j<3;j++) {
 53             in[i][j]=make_pair(-1,-1);
 54             out[i][j]=make_pair(-1,-1);
 55         }
 56     }
 57     for (int i=1;i<=n;i++) {
 58         for (int j=1;j<=n;j++) {
 59             if (i==j) continue;
 60             if (dis[i][j]==-1) continue;
 61             upd(make_pair(dis[i][j],i),in[j]);
 62             upd(make_pair(dis[i][j],j),out[i]);
 63         }
 64     }
 65     int best=0;
 66     int a=-1,b=-1,c=-1,d=-1;
 67     for (int i=1;i<=n;i++) {
 68         for (int j=1;j<=n;j++) {
 69             if (i==j) continue;
 70             if (dis[i][j]==-1) continue;
 71             for (int p=0;p<3;p++) {
 72                 if (in[i][p].first==-1) continue;
 73                 int ii=in[i][p].second;
 74                 if (ii==j) continue;
 75                 for (int q=0;q<3;q++) {
 76                     if (out[j][q].first==-1) continue;
 77                     int jj=out[j][q].second;
 78                     if (jj==i||jj==ii) continue;
 79 
 80                     int tot=dis[ii][i]+dis[i][j]+dis[j][jj];
 81                     if (tot>best) {
 82                         best=tot;
 83                         a=ii;b=i;c=j;d=jj;
 84                     }
 85                 }
 86             }
 87         }
 88     }
 89     printf("%d %d %d %d\n",a,b,c,d);
 90 }
 91 int main () {
 92     int m;
 93     scanf("%d %d",&n,&m);
 94     for (int i=1;i<=m;i++) {
 95         int u,v;
 96         scanf("%d %d",&u,&v);
 97         edge[u].push_back(v);
 98     }
 99     solve();
100     return 0;
101 }
View Code

 

posted @ 2016-05-05 23:59  活在夢裡  阅读(254)  评论(0编辑  收藏  举报