zoukankan      html  css  js  c++  java
  • 洛谷 P4926 [1007]倍杀测量者

    Description

    洛谷传送门

    Solution

    一道差分约束好题。

    题目要求我们输出最大的 (T) 使得至少有一个人女装。

    那么容易想到二分答案

    所以这道题就很明显了,二分答案套差分约束,判断是否符合条件。

    再来看如何建图。

    1. 对于 (C_A > C_B * k),我们从 (B)(A) 连一条权值为 (k) 的边。

    2. 对于已知分数的选手 (C_i = k),我们设一个 0 节点,且 (S_0 = 1),然后我们从 0 向 (i) 连权值为 (k) 的边,从 (i) 向 0 连权值为 (frac {1}{k}) 的边。

    然后跑一遍最长路,判断是否有环。

    如果有就符合条件。

    注意:这里的最长路是乘法运算

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    #define eps 1e-8
    #define ll long long
    
    using namespace std;
    
    const ll N = 1010;
    ll n, s, t;
    double l, r;
    struct Upd{
    	ll op, a, b, k;
    }tmp[N];
    ll c[N];
    struct node{
    	ll v, nxt;
    	double w;
    }edge[N << 1];
    ll head[N], tot;
    double dis[N];
    ll vis[N], cnt[N];
    queue <ll> q;
    
    inline void add(ll x, ll y, double z){
    	edge[++tot].v = y;
    	edge[tot].w = z;
    	edge[tot].nxt = head[x];
    	head[x] = tot;
    }
    
    inline bool spfa(){
    	while(!q.empty()){
    		ll x = q.front();
    		for(ll i = head[x]; i; i = edge[i].nxt){
    			ll y = edge[i].v;
    			if(dis[y] >= dis[x] * edge[i].w) continue;
    			dis[y] = dis[x] * edge[i].w;
    			cnt[y] = cnt[x] + 1;
    			if(cnt[y] == n + 2) return 1;
    			if(!vis[y])  q.push(y), vis[y] = 1;
    		}
    		q.pop(), vis[x] = 0;
    	}
    	return 0;
    }
    
    inline bool check(double T){
    	memset(head, 0, sizeof(head));
    	memset(cnt, 0, sizeof(cnt));
    	while(!q.empty()) q.pop();
    	tot = 0;
    	dis[0] = vis[0] = 1;
    	q.push(0);
    	for(ll i = 1; i <= n; i++){
    		dis[i] = vis[i] = 1;
    		q.push(i);
    		if(c[i]) add(i, 0, 1.0 / c[i]), add(0, i, c[i]);
    	}
    	for(ll i = 1; i <= s; i++){
    		if(tmp[i].op == 1) add(tmp[i].b, tmp[i].a, tmp[i].k - T);
    		else add(tmp[i].b, tmp[i].a, 1.0 / (tmp[i].k + T));
    	}
    	return spfa();
    }
    
    signed main(){
    	scanf("%lld%lld%lld", &n, &s, &t);
    	l = 0, r = 1e18;
    	for(ll i = 1; i <= s; i++){
    		ll op, a, b, k;
    		scanf("%lld%lld%lld%lld", &op, &a, &b, &k);
    		tmp[i] = (Upd){op, a, b, k};
    		if(op == 1) r = min(r, 1.0 * k);
    	}
    	for(ll i = 1; i <= t; i++){
    		ll p, x;
    		scanf("%lld%lld", &p, &x);
    		c[p] = x;
    	}
    	double ans = -1;
    	while(r - l > eps){
    		double mid = (l + r) / 2;
    		if(check(mid)) ans = mid, l = mid;
    		else r = mid;	
    	}
    	if(ans == -1) puts("-1");
    	else printf("%.10lf
    ", ans);
    	return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15364957.html

  • 相关阅读:
    7.31 "简单"(大嘘)DP
    P2014 选课
    7.30 "简单"(大嘘)DP
    Codeforce 1131C Birthday (构造数组)
    洛谷 P1074【靶形数独】(DFS)
    NOIP2004【虫食算】(DFS)
    洛谷 P1025【数的划分】(DFS dp)
    洛谷P1019【单词接龙】(DFS)
    洛谷P1162【机器人搬重物】(BFS)
    洛谷P1141【01迷宫】
  • 原文地址:https://www.cnblogs.com/xixike/p/15364957.html
Copyright © 2011-2022 走看看