• 2月4日 考试——迟到的 ACX


                        迟到的 ACX
                        时限:1s
                      内存限制:128MB
    题目描述:
      今天长沙下雪了,小 ACX 在上学路上欣赏雪景,导致上学迟到,愤怒的佘总给 ACX 巨佬出了一个题目想考考
    他,现在他找到你,希望你能帮帮他。
    对于一张有向图,要你求图中最小环的平均值最小是多少,即若一个环经过 k 个节点,那么这个环的平均值为
    环上 k 条边权的和除以 k,现要求其中的最小值。
    考虑到在座的各位都是巨佬,本题需要保留小数点后面八位。
    读入格式:
      第一行 2 个正整数,分别为 n 和 m ,并用一个空格隔开,分别表示图中有 n 个点 m 条边。 接下来 m 行,
    每行 3 个数 i,j,w 表示有一条边(i,j)且该边的权值为 w。输入数据保证图连通,存在环且有一个点能到达其他所有
    点。
    输出格式:
      请输出一个实数及最小环的平均值,要求输出到小数点后 8 位。
    样例输入:
    4 5
    1 2 5
    2 3 5
    3 1 5
    2 4 3
    4 1 3
    样例输出:
    3.66666667
    数据范围:
    100%的数据: n<=3000 m<=10000 |wi,j|<=10^7

     

    Solution:

      看到这题一个很好的思路就是二分答案,把问题转化成判定性问题。二分答案后,将每条边的边权都减去答案Ans,那么问题就转变成了判定一幅图中是否存在负环,一个经典的做法就是用Spfa,判断一个点有没有被加入超过N次,如果有则存在负环,可是这个复杂度是O(NM)的,不能通过本题。还有一种判负环的思想就是用Dfs来跑Spfa,然后一个点重复出现时就存在负环。具体实现可以一开始把所有点的初始距离设为0,然后枚举以每个点位开头是否存在负环,因为一个负环总有一个位置开始到每个点的路径都是负数。用这种做法就可以通过本题了。

    代码:

      

     1 /*本题不要想歪,直接二分+spfa,不多bb——by 520*/
     2 #include<bits/stdc++.h>
     3 #define il inline 
     4 #define ll long long 
     5 #define debug printf("%d %s
    ",__LINE__,__FUNCTION__)
     6 using namespace std;
     7 int n,m,cnt,h[3020];
     8 double dis[3020],ans;
     9 struct edge{
    10     int to,net;double val;
    11 }e[52000];
    12 bool vis[3020],bj;
    13 il void add(int u,int v,double w)
    14 {
    15     e[++cnt].net=h[u],h[u]=cnt,e[cnt].to=v,e[cnt].val=w;
    16 }
    17 il void spfa(int x)
    18 {
    19     vis[x]=1;
    20     for(int i=h[x];i;i=e[i].net){
    21         int v=e[i].to;
    22         if(dis[x]+e[i].val-ans<dis[v]){
    23             if(vis[v]){ bj=1;return;}
    24             dis[v]=dis[x]+e[i].val-ans;
    25             spfa(v);
    26             if(bj)return;
    27         }
    28     }
    29     vis[x]=0;
    30 }
    31 il bool check()
    32 {
    33     memset(dis,0,sizeof(dis));
    34     memset(vis,0,sizeof(vis));
    35     for(int i=1;i<=n;i++){
    36         bj=0;spfa(i);
    37         if(bj)return 1;
    38     }
    39     return 0;
    40 }
    41 int main()
    42  {
    43     freopen("late.in","r",stdin);
    44     freopen("late.out","w",stdout);
    45     scanf("%d%d",&n,&m);
    46     int u,v;double w;
    47     for(int i=1;i<=m;i++)scanf("%d%d%lf",&u,&v,&w),add(u,v,w);
    48     double l=-2333333,r=2333333;
    49     while(r-l>1e-9){
    50         ans=(l+r)/2;
    51         if(check())r=ans;
    52         else l=ans;
    53     }
    54     printf("%.8lf",ans);
    55     return 0;
    56 }

     

     

  • 相关阅读:
    一、left
    padding溢出
    一、
    Python创建、删除桌面、启动组快捷方式的例子分享
    openstack常见问题解决方法总结
    __attribute__ 详解
    __ATTRIBUTE__ 知多少?
    CentOS如何设置终端显示字符界面区域的大小
    shell使用技巧
    openstack 安全策略权限控制等api接口
  • 原文地址:https://www.cnblogs.com/five20/p/8413111.html
Copyright © 2020-2023  润新知