zoukankan      html  css  js  c++  java
  • 20140705 testA 二分答案

    testA

    输入文件: testA.in  输出文件testA.out 时限2000ms

    问题描述:

            有一个城市拥有N个节点,被M条有权无向路径连接。现在你要在一个地方(可以在路径上当然也可以在节点上)开设一家咖啡馆,使得所有节点达到这个咖啡馆的最短路里面最大值最小(也就是说离咖啡馆最远的节点距离尽可能得小),求出这个最大值的最小值。

    输入描述:

    第一行N和M。

    第2至M+1行,每行三个整数U,V,W。表示从U到V有一条权值为W的无向边。

    输出描述:

    一行一个数表示答案。 四舍五入至2位小数

    数据范围 N<=200 , W<=100000 , M<=19900

    样例输入:

    3 2
    1 2 100
    2 3 1

    样例输出:

    50.50

      

    由于可以取边上的点 于是毫无头绪 写的最小生成树之后取最长边/2 竟然有20分-_-

    解题报告也没有看懂

    解题报告:

        

      注意这道题可以选在边上进行咖啡馆的选择。

      要找出一个最小距离的点不是很容易,但是判断一个答案是否是合法的可以迅速解决。

      假设答案是L

      我们枚举一条边(x,y,w),判断在这条边上建立咖啡馆是否合法。

      那么从一个点k到达咖啡馆有两种选择

      (1)  k->x->咖啡馆  (2)  k->y->咖啡馆

      设l = L-d[x][y] , r = L-d[y][k]

      那么当l<0 并且r<0时肯定不能在这条边上建立咖啡馆

      当l>=w或者r>=w时 或者 l+r >= w 时 一定合法

           否则 要么在x->y的路径的l长度之内建立咖啡馆或者在y->x的路径的长度r之内建立咖啡馆。

      那么从l+0.5到w-r-0.5这段区间对于k来说并不合法。

      对于每个点k求出这样的区间,如果他们的并是整个区间[0,w],则这条边不能建立咖啡馆。

      对于L来说只要有一条边上可以满足条件则满足条件。

      二分L再进行判断。复杂度是O(30MN)。 最后的结果肯定是整数或者是整数+0.5。所以先对所有边*2避免小数运算。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <vector>
     5 using namespace std;
     6 #define INF 0x3f3f3f
     7 #define N 220
     8 
     9 struct edges {
    10     int v,l;
    11 };
    12 struct interval {
    13     int left,right;
    14 };
    15     
    16 vector <edges> edge[N];
    17 int n,m;
    18 int dis[N][N];
    19 
    20 bool cmp(interval a,interval b) {
    21     if (a.left==b.left) return a.right<b.right;
    22     return a.left<b.left;
    23 }
    24 
    25 bool check(int L) {
    26     vector <interval> v;
    27     for (int i=1;i<=n;i++) {
    28         for (int j=0;j<edge[i].size();j++) {
    29             v.clear();
    30             int x=i, y=edge[i][j].v, w=edge[i][j].l, k;
    31             for (k=1;k<=n;k++) {
    32                 int l=L-dis[x][k];
    33                 int r=L-dis[y][k];
    34                 if (l<0) l=-1;
    35                 if (r<0) r=-1;
    36                 if (l>=w || r>=w) continue;
    37                 if (l+r>=w) continue;
    38                 if (l==-1 && r==-1) break;
    39                 interval vv;
    40                 vv.left=l+1; vv.right=w-r-1;
    41                 v.push_back(vv);
    42             }
    43             if (k==n+1) {
    44                 if (v.empty()) return true;
    45                 sort(v.begin(),v.end(),cmp);
    46                 int last=0;
    47                 for (int t=0;t<v.size();t++) {
    48                     if (last<v[t].left) return true;
    49                     if (v[t].right+1>last) last=v[t].right+1;
    50                 }
    51             }
    52         }
    53     }
    54     return false;
    55 }
    56  
    57  
    58 void solve() {
    59     int l=0,r=INF;
    60     int ans;
    61     while (l<=r) {
    62         int mid=(l+r)/2;
    63         if (check(mid)) {
    64             ans=mid;
    65             r=mid-1;
    66         }
    67         else {
    68             l=mid+1;
    69         }
    70     }
    71     printf("%.2f",double(ans)/2.0);
    72 }
    73 
    74 int main() {
    75     memset(dis,INF,sizeof(dis));
    76     scanf("%d%d",&n,&m);
    77     for (int i=1;i<=n;i++) dis[i][i]=0;
    78     for (int i=0;i<m;i++) {
    79         int u,v,l;
    80         edges e;
    81         scanf("%d%d%d",&u,&v,&l);
    82         l=l*2;
    83         e.v=v; e.l=l;
    84         edge[u].push_back(e);
    85         dis[v][u]=dis[u][v]=min(dis[v][u],l);
    86     }
    87 
    88     for (int k=1;k<=n;k++) {
    89         for (int i=1;i<=n;i++) {
    90             for (int j=1;j<=n;j++) {
    91                 dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
    92             }
    93         }
    94     }
    95     
    96     solve();
    97 }
    View Code
  • 相关阅读:
    python通过openpyxl操作excel
    python实现将字符串中以大写字母开头的单词前面添加“_”下划线
    python unittest setUp 和 setUpClass 区别
    python selenium 定制启动Chrome的选项注意事项(十九)
    Python 回调函数
    python 面试题
    python 常用的模块
    MySQL通过分组计算百分比
    mybatis 动态sql 的笔记 以及标签
    resultMap自定义映射---8.3.1. 解决列名(表中的字段名称)和实体类中的属性名不一致
  • 原文地址:https://www.cnblogs.com/fjmmm/p/3828479.html
Copyright © 2011-2022 走看看