zoukankan      html  css  js  c++  java
  • BZOJ1486 [HNOI2009]最小圈

    Description

    Input

    Output

    Sample Input

    4 5
    1 2 5
    2 3 5
    3 1 5
    2 4 3
    4 1 3

    Sample Output

    3.66666667
     
     
    正解:SPFA+二分答案
    解题报告:
      分数规划,具体我不是很会证,传送门:http://blog.csdn.net/fzhvampire/article/details/49454627
      大概意会一下还是可以理解的。
      首先对于这种问题我觉得有一点通项公式的味道,像上次做的黑边、白边的题目,也是同样的。因为我们想得到某个权值,需要对边进行操作。
      比如说这道题,要求最小圈平均权值。显然如果我们先二分答案变成判定性问题会好做一些。二分一个答案ans,将每条边都减去ans,然后SPFA找负权环,如果找到了就说明这个ans可以成为最小圈平均权值,但是还不够优。所以我们需要不断试探,直到精度满足要求。至于判环,用DFS版的SPFA应该要比BFS版的快很多。
      注意一下精度问题,要求8位,那么必须要二分到9位,第一次就因为这个WA了一次。
      常见思路:二分一个答案,每条边减去,再进行判定与check
     
     
      
     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 #ifdef WIN32   
    14 #define OT "%I64d"
    15 #else
    16 #define OT "%lld"
    17 #endif
    18 using namespace std;
    19 typedef long long LL;
    20 const int MAXN = 3011;
    21 const int MAXM = 20011;
    22 const double eps = 0.000000001;
    23 int n,m,ecnt;
    24 int first[MAXN],u[MAXM],v[MAXM];
    25 double w[MAXM],dis[MAXN];
    26 double l,r,mid,ans;
    27 bool ok;
    28 bool vis[MAXN];
    29 struct edge{
    30     int next,to;
    31     double w;
    32 }e[MAXM];
    33 
    34 inline int getint()
    35 {
    36        int w=0,q=0;
    37        char c=getchar();
    38        while((c<'0' || c>'9') && c!='-') c=getchar();
    39        if (c=='-')  q=1, c=getchar();
    40        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
    41        return q ? -w : w;
    42 }
    43 
    44 inline void link(int x,int y,double z){ e[++ecnt].next=first[x]; first[x]=ecnt; e[ecnt].to=y; e[ecnt].w=z;   }
    45 
    46 inline void SPFA(int x){//DFS版SPFA找负权环,只有碰到负边才走
    47     vis[x]=1;
    48     for(int i=first[x];i;i=e[i].next){
    49     int v=e[i].to;
    50     if(dis[v]>dis[x]+e[i].w) {
    51         if(vis[v]) { ok=true; return ; }
    52         dis[v]=dis[x]+e[i].w; SPFA(v);
    53         if(ok) return ;
    54     }
    55     }
    56     vis[x]=0;//退出时记得清空标记
    57 }
    58 
    59 inline bool check(double val){
    60     memset(first,0,sizeof(first)); ecnt=0;
    61     memset(vis,0,sizeof(vis));
    62     memset(dis,0,sizeof(dis));
    63     ok=false; for(int i=1;i<=m;i++) link(u[i],v[i],w[i]-val);
    64     for(int i=1;i<=n;i++) {
    65     SPFA(i);//DFS版SPFA
    66     if(ok) return true;
    67     }
    68     return false;
    69 }
    70 
    71 inline void work(){
    72     n=getint(); m=getint();
    73     for(int i=1;i<=m;i++) u[i]=getint(),v[i]=getint(),scanf("%lf",&w[i]);
    74 
    75     l=-10000000; r=10000000;
    76     while(r-l>eps) {
    77     mid=(l+r)/2.0;
    78     if(check(mid)) ans=mid,r=mid;//已经产生负权环
    79     else l=mid;
    80     }
    81     printf("%.8lf",ans);
    82 }
    83 
    84 int main()
    85 {
    86   work();
    87   return 0;
    88 }
  • 相关阅读:
    保持简单----纪念丹尼斯•里奇(Dennis Ritchie)
    转:有关retina和HiDPI那点事
    Powershell 学习
    Windows与Linux共享文件夹互相访问
    你知道C语言为什么会有“_”(下划线)吗?
    百度公共DNS
    AXIS2的一些认识
    待整理
    java复习汇总之面试篇
    落网歌曲图片下载
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5758362.html
Copyright © 2011-2022 走看看