• 观光奶牛Sightseeing Cows (二分+spfa(dfs))


    观光奶牛

    农夫约翰已决定通过带他们参观大城市来奖励他们的辛苦工作!奶牛必须决定如何最好地度过他们的空闲时间。

    幸运的是,他们有一个详细的城市地图,显示L(2≤L≤1000)主要地标(方便编号为1 .. L)和P(2≤P≤5000)单向奶牛路径加入它们。农夫约翰将把奶牛带到他们选择的起始地标,从那里他们将沿着牛路走到一系列其他地标,最后回到他们的起始地标,农民约翰将把他们捡起来带回农场。因为城市中的空间非常宝贵,所以奶牛路径非常狭窄,因此沿着每个奶牛路径行进仅允许在一个固定方向上行进。

    虽然奶牛可能会在城市中花费尽可能多的时间,但他们确实很容易感到厌倦。访问每个新地标很有趣,但在它们之间行走需要时间。奶牛知道每个地标i的确切有趣值Fi(1≤Fi≤1000)。

    奶牛也知道奶牛的路径。Cowpath i将地标L1i连接到L2i(方向L1i - > L2i)并且需要时间Ti(1≤Ti≤1000)来遍历。

    为了尽可能享受最佳休息日,奶牛希望最大限度地提高每次旅行单位时间的平均乐趣价值。当然,这些地标在他们第一次参观时才很有趣; 奶牛可能不止一次穿过地标,但他们再也没有看到它的有趣价值。此外,Farmer John正在让奶牛至少访问两个标志性建筑,以便他们在休息期间进行一些锻炼。

    帮助奶牛找到每单位时间可以达到的最大乐趣值。

    这道题显然你看到最大的乐趣值,就知道这道题需要二分。
    二分啥呢?题目要求你求啥你就二分啥。
    另外题目需要牛转一个环,很明显就是负环,因为我们要使得乐趣/时间最大,所以在预处理后我们要让他尽量的小,这就出现了负环。
    因为bfs版spfa会T,所以我们应该用dfs版。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 51000
    using namespace std;
    bool vis[N];
    int n,m,x,y,z,tot;
    int c[N],num[N],head[N];
    double ans,mid,l,r,w[N],dis[N];
    
    struct Edge {
    	int to,dis,next;
    } e[N];
    
    int add(int x,int y,int z) {
    	e[++tot].to=y;
    	e[tot].dis=z;
    	e[tot].next=head[x];
    	head[x]=tot;
    }
    
    int read() {
    	int x=0,f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9') {
    		if(ch=='-')f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9') {
    		x=x*10+ch-'0';
    		ch=getchar();
    	}
    	return x*f;
    }
    
    bool spfa(int x) {
    	vis[x]=true;
    	for(int i=head[x]; i; i=e[i].next) {
    		int t=e[i].to;
    		if(dis[t]>dis[x]+w[i]) {
    			dis[t]=dis[x]+w[i];
    			if(vis[t]||spfa(t)) {
    				vis[x]=false;
    				return true;
    			}
    		}
    	}
    	vis[x]=false;
    	return false;
    }
    
    bool judge() {
    	for(int i=1; i<=n; i++)
    		if(spfa(i)) return true;
    	return false;
    }
    
    int main() {
    	n=read(),m=read();
    	for(int i=1; i<=n; i++) c[i]=read();
    	for(int i=1; i<=m; i++) {
    		x=read(),y=read(),z=read();
    		add(x,y,z);
    	}
    	l=0,r=20000;
    	while(r-l>0.0000001) {
    		mid=(l+r)/2;
    		for(int i=1; i<=tot; i++) {
    			int t=e[i].to;
    			w[i]=(double)mid*e[i].dis-c[t];
    		}
    		if(judge()) {
    			ans=mid;
    			l=mid;
    		} else r=mid;
    	}
    	printf("%.2lf",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    VSFTPD无法上传的解决方法
    linux下vsftpd的安装与配置说明
    长轮询
    采用handle消息机制实现轮播效果
    开启AsyncTask从网络加载图片
    使用异步httpclient框架做get,post提交数据
    使用post方式提交数据
    使用get方式提交数据
    json,xml,Html解析
    常用的有关文件上传下载的框架和图片加载框架
  • 原文地址:https://www.cnblogs.com/ifmyt/p/9781817.html
Copyright © 2020-2023  润新知