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 }