• poj 3621 Sightseeing Cows (最优比率环)


    http://poj.org/problem?id=3621

    题意:

    给定 一些 点的 欢乐值 ,和一些点的距离 ,求 是否存在一个环使得 ,欢乐值 /走的总距离,   最大 ;

    题解:整数规划 问题。 

    首先的一个结论就是,不会存在环套环的问题,即最优的方案一定是一个单独的环,而不是大环套着小环的形式。这个的证明其实非常的简单,大家可以自己想一下 (提示,将大环上的收益和记为x1,花费为y1,小环上的为x2,y2。重叠部分的花费为S。表示出来分类讨论即可)。有了这个结论,我们就可以将花费和 收益都转移到边上来了,因为答案最终一定是一个环,所以我们将每一条边的收益规定为其终点的收益,这样一个环上所有的花费和收益都能够被正确的统计。
    解决了蛋疼的问题之后,就是01分数规划的部分了,我们只需要计算出D数组后找找有没有正权环即可,用spfa(单源最短路径) 判断即可。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<set>
      7 #include<map>
      8 #include<queue>
      9 #include<vector>
     10 #include<string>
     11 #define Min(a,b) a<b?a:b
     12 #define Max(a,b) a>b?a:b
     13 #define CL(a,num) memset(a,num,sizeof(a));
     14 #define eps  1e-6
     15 #define inf 10001000
     16 
     17 #define ll   __int64
     18 
     19 #define  read()  freopen("data.txt","r",stdin) ;
     20 const double pi  = acos(-1.0);
     21 const int maxn = 1024;
     22 
     23 using namespace std;
     24 struct node
     25 {
     26     int u;
     27     int v;
     28     int len ;
     29     int next ;
     30 }p[maxn*5] ;
     31 int n , m ;
     32 int cnt , head[maxn],num[maxn],a[maxn];
     33 double dis[maxn];
     34 int vis[maxn] ;
     35 void add(int u,int v,int len )
     36 {
     37     p[cnt].v = v;
     38     p[cnt].len = len;
     39     p[cnt].next = head[u] ;
     40     head[u] = cnt++ ;
     41 }
     42 
     43 queue<int>que;
     44 bool spfa(double mid)
     45 {
     46     int  i ;
     47     while(!que.empty())que.pop() ;
     48     
     49     for(i = 1 ; i <= n;i++)
     50     {
     51         dis[i] = -inf;
     52 
     53 
     54     }
     55 
     56     que.push(1) ;
     57     
     58     dis[1] = 0;
     59     
     60     CL(vis,0) ;
     61     
     62     vis[1] = 1;
     63 
     64     CL(num,0) ;
     65 
     66 
     67 
     68     while(!que.empty())
     69     {
     70         int u = que.front() ;que.pop() ;
     71         vis[u] = 0 ;
     72         for(i = head[u];i !=-1 ;i = p[i].next)
     73         {
     74             int v = p[i].v ;
     75             int len = p[i].len ;
     76             double t = a[v] - mid * len ;
     77             if(dis[u]  + t >  dis[v])
     78             {
     79                 dis[v] = t + dis[u];
     80                num[v] ++;
     81                 if(!vis[v])
     82                 {
     83                     que.push(v) ;
     84                     vis[v] = 1 ;
     85 
     86 
     87                 }
     88                 if(num[v] >= n) return true ;
     89 
     90 
     91 
     92             }
     93         }
     94 
     95     }
     96     return false ;
     97 }
     98 int main()
     99 {
    100     int i ;
    101     int x,y;
    102     int d;
    103     //read() ;
    104     while(scanf("%d%d",&n,&m)!=EOF)
    105     {
    106         cnt =  0 ;
    107         CL(head,-1) ;
    108         for(i = 1  ;i <=  n;i++)
    109           scanf("%d",&a[i]) ;
    110         for(i = 0  ; i< m;i++)
    111         {
    112             scanf("%d%d%d",&x,&y,&d) ;
    113             add(x,y,d);
    114 
    115         }
    116         double  l = 0, r = 2500,mid;
    117         double ans = -1;
    118         while(r - l >= eps)
    119         {
    120             mid = (l + r)/2.0 ;
    121             if(spfa(mid))
    122             {
    123                 ans = mid;
    124                 l = mid ;
    125             }
    126             else r = mid ;
    127         }
    128 
    129         if(ans < 0)printf("0\n");//判断是否有环
    130         else
    131         printf("%.2lf\n",ans) ;
    132 
    133 
    134     }
    135 }



  • 相关阅读:
    图像处理之图像分割
    matlab 矩阵运算技巧
    回溯法:八皇后问题
    spring框架学习笔记(二)
    spring框架学习笔记(一)
    java下搭建Webservice服务
    log4j使用
    Mybatis使用
    java序列化与反序列化
    java常用数据类型
  • 原文地址:https://www.cnblogs.com/acSzz/p/2713011.html
Copyright © 2020-2023  润新知