P4926 [1007]倍杀测量者

原题链接

考察:差分约束+二分

这题太呕了,调bug调了几个小时.

错误思路:

       贪心,根据已经确定成绩的A,B求解最大值T.

       可能存在这样的情况:a要k+T倍杀b,c要被b k-T倍杀,已知a、c的分数。那么有可能b无论取什么分数,这两个flag至少会不满足一个,也就是说可能会这样:b取大了a不能k+T倍杀b,b取小了b不能k-T倍杀c,结果b取什么都无法同时满足两个flag,这时候的T也是满足条件的。所以这题要先二分T,然后用差分约束来判断。(好像是这样的QAQ) 来自luogu 讨论区的 Zechariah 大佬

       意思就是说, 假设 a>=(k+T) * b > = (k1+T)*(k2-T)*c  如果无论如何 c与a不满足关系,那么就一定有人女装,此时T取任意值,b无需知道值.

思路:

       之前的最短路问题,spfa和dijkstra算法的 dist[v] >dist[u]+road[i].w 换成乘法也一样成立.那么这题也一样.

       对于flag 1: A/B >= K-T 就不女装

       对于flag 2: B/A<K+T 就不女装.

       对于每一个flag,只要题目所给不等式全部成立就不需要女装.所以至少有一个人女装的条件是不等式不成立,即存在环.

       T显然有单调性,所以可以二分.

        这里建立虚拟源点0,分数>=0所以可以全部连上边.

记录一下本蒟蒻的坑点:

       恢复dist[i] = 0的时候忘了i<=s.然后T是<=所有flag1的k的最小值.不包括flag 2

 1 #include <iostream>
 2 #include <cstring>
 3 #include <stack>
 4 using namespace std;
 5 const double eps = 1e-8;
 6 const int N = 1010,INF = 0x3f3f3f3f; 
 7 int n,s,t,h[N],idx,cnt[N],score[N];
 8 double dist[N];
 9 bool st[N];
10 struct Road{
11     int fr,to,ne;
12     double w;
13 }road[N<<2];
14 struct Node{
15     int o,a,b,k;
16 }node[N];
17 void add(int a,int b,double w)
18 {
19     road[idx].fr = a,road[idx].to = b,road[idx].w = w,road[idx].ne = h[a],h[a] = idx++;
20 }
21 bool spfa(double mid)
22 {
23     memset(h,-1,sizeof h); memset(cnt,0,sizeof cnt);
24     memset(st,0,sizeof st);
25     idx = 0;
26     for(int i=1;i<=s;i++)
27     {
28         int a = node[i].a,b = node[i].b,k = node[i].k,type = node[i].o;
29         if(type==1) add(b,a,k-mid);
30         else add(b,a,1.0/(k+mid));
31     }
32     for(int i=1;i<=n;i++)
33     {
34         if(score[i]!=-1) add(0,i,score[i]),add(i,0,1.0/score[i]);
35         else add(0,i,0);
36         dist[i] = 0;
37     }
38     stack<int> q;
39     dist[0] = 1; st[0] = 1;
40     q.push(0);
41     while(q.size())
42     {
43         int u = q.top();
44         q.pop();
45         st[u] = 0;
46         for(int i=h[u];~i;i=road[i].ne)
47         {
48             int v = road[i].to;
49             if(dist[v]<dist[u]*road[i].w)
50             {
51                 dist[v] = dist[u]*road[i].w;
52                 cnt[v] = cnt[u]+1;
53                 if(cnt[v]>=n+1) return 1; 
54                 if(!st[v]) q.push(v),st[v] = 1;
55             }
56         }
57     }
58     return 0;
59 }
60 int main()
61 {
62     scanf("%d%d%d",&n,&s,&t);
63     memset(score,-1,sizeof score);
64     double l = 0,r = 11;
65     for(int i=1;i<=s;i++)
66     {
67         int o,a,b,k;
68         scanf("%d%d%d%d",&o,&a,&b,&k);
69         node[i] = {o,a,b,k};
70     }
71     while(t--)
72     {
73         int c,x; scanf("%d%d",&c,&x);
74         score[c] = x;
75     }
76     while(r-l>=eps)
77     {
78         double mid = (l+r)/2;
79         if(spfa(mid)) l = mid;
80         else r = mid;
81     }
82     if(r>eps) printf("%.10lf\n",r);
83     else puts("-1");
84     return 0;
85 }

 

posted @ 2021-05-09 12:59  acmloser  阅读(66)  评论(0编辑  收藏  举报