• bellman_ford寻找平均权值最小的回路


    给定一个有向图,如果存在平均值最小的回路,输出平均值。

    使用二分法求解,对于一个猜测值mid,判断是否存在平均值小于mid的回路

    如果存在平均值小于mid的包含k条边的回路,那么有w1+w2+w3+...+wk < k * mid,即(w1-mid)+(w2-mid)+..(wk-mid)<0,

    即判断是否存在负权回路即可。

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=2031&mosmsg=Submission+received+with+ID+14572787

     1 #include <stdio.h>
     2 #include <string.h>
     3 const int N = 50+10;
     4 const int INF = 1<<30;
     5 struct Edge
     6 {
     7     int u,v;
     8     double weight;
     9 }g[4000000];
    10 double dist[N];
    11 void relax(int u, int v,double weight)
    12 {
    13     if(dist[v] > dist[u] + weight)
    14         dist[v] = dist[u] + weight;
    15 }
    16 bool bellman_ford(int n, int m)
    17 {
    18     int i,j;
    19     for(i=0; i<n-1; ++i)//n-1循环
    20         for(j=0; j<m; ++j)//枚举所有的边去松弛最短路径
    21         {
    22             relax(g[j].u,g[j].v,g[j].weight);
    23         }
    24     bool flag = false;
    25     for(i=0; i<m; ++i)
    26         if(dist[g[i].v] > dist[g[i].u] + g[i].weight)
    27         {
    28             flag = true;
    29             break;
    30         }
    31     return flag;
    32 }
    33 bool test(double x,int n, int m)
    34 {
    35     int i;
    36     for(i=0; i<m; ++i)
    37         g[i].weight -= x;
    38     bool ret =  bellman_ford(n,m);
    39     for(i=0; i<m; ++i)
    40         g[i].weight += x;
    41     return ret;
    42 }
    43 int main()
    44 {
    45     int n,m,i,t,tCase=1;
    46     double l,r;
    47     scanf("%d",&t);
    48     while(t--)
    49     {
    50         scanf("%d%d",&n,&m);
    51         for(i=1; i<=n; ++i)
    52             dist[i] = INF;
    53         l = r = 0;
    54         for(i=0; i<m; ++i)
    55         {
    56             scanf("%d%d%lf",&g[i].u,&g[i].v,&g[i].weight);
    57             r = r > g[i].weight ? r : g[i].weight;
    58         }
    59         if(!test(r+1,n,m))printf("Case #%d: No cycle found.
    ",tCase++);
    60         else
    61         {
    62             double mid;
    63         
    64             while(r-l>0.001)//因为题目要求保留2位小数,所以当r-l>0.001时,l就是答案。
    65             {
    66                 double mid = (r + l ) / 2;
    67                 if(test(mid,n,m))
    68                     r = mid;
    69                 else
    70                     l = mid;
    71             }
    72             printf("Case #%d: %.2lf
    ",tCase++,l);
    73         }
    74         
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    小问题也是大问题
    Java GC(2)
    Java GC(1)
    mac eclipse svn
    svn merge
    LTE,WiMAX与WIFI相关知识链接整理
    【LTE基础知识】承载相关概念介绍
    【LTE基础知识】LTE空口协议分析
    LTE基础知识
    Scapy学习2
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4116615.html
Copyright © 2020-2023  润新知