Cf163#2 problem D

http://codeforces.com/contest/266/problem/D

这是一道最短路的题目,比赛的时候想到最短路算法,也想到二分,但细节还是没想清楚,导致挂了。。

后来比赛完之后感觉2分有问题,

就想到三分法,然后写了下,一直没法ac。。(而且也担心时间问题),最后还是用二分ac之。。

最初枚举边,把边断掉,边的两端点各做一遍的spfa,对于结果点进行3分枚举(因为其满足单峰,也就是满足类似抛物线形)

然后去最小值与当前最优答案比较,更优着替换。

发现这样第9点就TLE了。。。因为条边都要做一遍的spfa,时间复杂度太高了(实际上没必要每次用spfa)

所以今天就改为先用floyd处理出任意两点间的最短距离mindist,在做三分。。。然后不知道怎么回事还是挂了(这个算法是没错的,因为有人这样3分过了)。。

再来说说后来发现最开始的2分法是可行的,但操作上有点变化。。

2分具体实现:1、 2分最大答案dist,然后判定

                   2、 然后判定在当前dist下,第各个点经过dist所能到覆盖到当前枚举边的范围

                   3、 对这些范围求公共区域,如果存在,则为合法解,否则不合法(即求解多个不等式)

                   4、根据返回的结果再二分,返回到1

注意:该题的结果不是不是整数就是含有0.5(因为所有的边都为整数,/2也就只有可能出现0.5,不会出现其他形式的小数),所以可以对边进行*2,变成整数操作。。做完ans/2.0即可。。。

       写这道题收获还是蛮多的,感觉挺拓宽思路的。。

Code:

  1 /*
  2  * Status: solve
  3  * User: Yzcstc
  4  * Resources: Codeforces 163#2 D 
  5  * Typical: Shortest paths
  6  * Time: 2013.01.24
  7  */
  8 #include <iostream>
  9 #include <fstream>
 10 #include <cstring>
 11 #include <cstdio>
 12 #include <cstdlib>
 13 #include <string>
 14 #include <algorithm>
 15 #include <vector>
 16 #define INF 1000000000
 17 #define MAXN 210
 18 using namespace std;
 19 struct edge{ int x , y , z; };
 20 struct oo{ int l,r ; };
 21 edge a[40000];
 22 oo  b[MAXN];
 23 int n , m , d[MAXN][MAXN];
 24 double ans;
 25 void init(){
 26       int x , y , z;
 27       scanf("%d",&n);
 28       scanf("%d",&m);
 29       for (int i = 1; i <= n; ++i)
 30          for (int j = 1; j <= n; ++j)
 31              if (i != j) d[i][j] = INF;
 32          
 33       for (int i = 1; i <= m; ++i){
 34             scanf("%d%d%d",&x,&y,&z);
 35             z <<= 1;
 36             d[x][y] = d[y][x] = z;
 37             a[i].x = x;
 38             a[i].y = y;
 39             a[i].z = z;
 40       }
 41 }
 42 
 43 void floyd(){   
 44      for (int k = 1; k <= n; ++k)
 45         for (int i = 1; i <= n; ++i)
 46            for (int j = 1; j <= n; ++j)
 47                 d[i][j] = min( d[i][j] , d[i][k] + d[k][j] );
 48 }
 49 
 50 bool cmp(const oo a, const oo b){
 51        if (a.l<b.l || a.l == b.l && a.r < b.r ) return true;
 52        return false;
 53 }
 54 
 55 int check(int dist){
 56      int tm , d1 , d2 , x , y , z , LL;
 57      bool flag;
 58      for (int i = 1; i <= m; ++i){
 59           x = a[i].x;
 60           y = a[i].y;
 61           z = a[i].z;
 62           LL = 0;
 63           flag = true;
 64           for (int j = 1; j <= n ; ++j){
 65                d1 = dist - d[x][j];
 66                d2 = dist - d[y][j];
 67                if (d1 >= z || d2 >= z) continue;
 68                if (d1 + d2 >= z) continue;
 69                if (d1 <0 && d2 <0 ) { 
 70                        flag = false;
 71                        break;
 72                }
 73                ++LL;
 74                b[LL].l = d1;
 75                b[LL].r = z - d2;
 76           }
 77           if (flag){
 78                if (!LL) return 1;
 79                sort( b+1, b+LL+1 ,cmp);
 80                tm = 0;
 81                for (int j = 1; j <= LL; ++j){
 82                     if (tm <= b[j].l) return 1;
 83                     if (tm < b[j].r) tm = b[j].r;
 84                }
 85           }
 86           
 87      }
 88      return 0;
 89 }
 90 
 91 void solve(){
 92      int l = 0, r = 2*INF, mid;
 93      while (r - l > 1){
 94             mid = (l + r) >> 1;
 95             if (check(mid)) r = mid;
 96             else l = mid;
 97      }
 98      if  (check(l)) ans = l;
 99      else ans = r;
100      printf("%0.1lf\n", ans / 2.0);
101 }
102 
103 int main(){
104      freopen("d.in","r",stdin);
105      freopen("d.out","w",stdout);
106      init();
107      floyd();
108      solve();
109 }

 

                  

posted on 2013-01-24 21:07  yzcstc  阅读(117)  评论(0)    收藏  举报