P1768 天路 SPFA判负环+二分

题意:给出一个图,每条边有两个权值,一个是观赏价值、一个是费用

   要我们求出一个环,要让(总的观赏价值/总的费用)的值最大

思路:我们二分来做这道题,对象为(总的观赏价值/总的费用),然后跑SPFA判负环;

    那么为什么是判负环呢

     我们设一个环的总观赏价值为V,费用为W  

     那么要想让当前查询对象满足,就要求出来的值>=mid

       即:V/W>=mid 

       故:  V>=mid*W

       故:mid*W-V<=0    

     所以,我们每次跑SPFA的时候,把每条边的权值改为mid*w-v,然后开始跑SPFA

     很明显,当出现负权环的时候,满足题意

     当大于0的时候,不满足

     当一个环的值等于0的时候,也满足题意,不过在这种情况下,我们默认不满足

        那为什么默认不满足也可以ac呢?这就要考虑到精度问题了。

        题目给出的精度只到了0.1,假如刚好搜(0.1)有一个环等于0 满足情况的话

        我们便会向左区间搜索,然后既然0.1满足情况,那么0.099999肯定也满足,这个时候就会是个负数环,而不是环等于0了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=7007;
 4 struct edge
 5 {
 6     int to,v,c;
 7 };
 8 vector<edge>G[maxn];
 9 int n,m;
10 bool vis[maxn];
11 double dis[maxn];
12 bool spfa(double ans,int now)//DFS版的SPFA
13 {
14     vis[now]=true;
15     for(int i=0;i<G[now].size();i++){
16         edge e=G[now][i];
17         double x=ans*e.c-e.v;//边的权值,根据二分出来的ans进行修改
18         if (dis[e.to]>dis[now]+x){
19             if (vis[e.to]) return false;
20             else{
21                 dis[e.to]=dis[now]+x;
22                 vis[now]=true;
23                 if (!spfa(ans,e.to)) return false;
24             }
25         }
26     }
27     vis[now]=false;//记得要回溯
28     return true;
29 }
30 int main()
31 {
32     scanf("%d%d",&n,&m);
33     for(int i=1;i<=m;i++){
34         int x,y,v,c;
35         scanf("%d %d %d %d",&x,&y,&v,&c);
36         G[x].push_back((edge){y,v,c});
37     }
38     for(int i=1;i<=n;i++){
39         G[0].push_back((edge){i,0,0});//超级点与每个点都需要联通
40     }
41     double l=0,r=1000001;//注意这里,l需要从0而不是1开始枚举。具体为什么自己想。
42     while(l+0.00001<r)//浮点数的精度问题,应该不需要我强调了?
43     {
44         memset(dis,127,sizeof(dis));
45         memset(vis,false,sizeof(vis));
46         dis[0]=0;vis[0]=true;
47         double mid=(l+r)/2;
48         if (spfa(mid,0)) r=mid;
49         else l=mid;
50         mid=(l+r)/2;
51     }
52     if(l==0) printf("-1\n");
53     else printf("%.1f\n",l);
54     return 0;
55 }
View Code

 

  

posted @ 2020-04-15 21:02  古比  阅读(159)  评论(0编辑  收藏  举报