其他分享
首页 > 其他分享> > 「USACO2007DEC」Sightseeing Cows 题解报告

「USACO2007DEC」Sightseeing Cows 题解报告

作者:互联网

题目大意

给定一张图,边上有花费,点上有收益,点可以多次经过,但是收益不叠加,边也可以多次经过,但是费用叠加。求一个环使得收益和/花费和最大,输出这个比值。

样例

样例输入1
5 7
30
10
10
5
10
1 2 3
2 3 2
3 4 5
3 5 2
4 5 5
5 1 3
5 2 2
样例输出1
6.00

思路

就是板子啦!

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+2;//max-n 
int n,m,cnt,x,y,z;
int fir[N],sum[N],vis[N],to[N<<1],nxt[N<<1];
double mid,dis[N],a[N],w[N<<1];
void add(int x,int y,int z){
	nxt[++cnt]=fir[x];
	fir[x]=cnt;
	to[cnt]=y;
	w[cnt]=z;
}//前向星建图_(:з」∠)_ 
bool spfa(int s){//判负环 
	memset(vis,0,sizeof(vis));//初始化 
	memset(sum,0,sizeof(sum));//初始化  1到x的最短路径包含的边数
	//用来判负环,cnt[x]>=n就表示有负环(原因显然好伐) 
	memset(dis,0x3f,sizeof(dis));//极大值 
	queue<int>q;
	q.push(s);
	vis[s]=1;//维护标记数组 
	dis[s]=0;//自己到自己距离显然为0(#`O′) 
	while(!q.empty()){
		int p=q.front();q.pop();
	  	for(int u=fir[p];u;u=nxt[u]){//遍历 
	  		int v=to[u];//方便书写︿( ̄︶ ̄)︿ 
			vis[v]=0;//维护标记数组 
	 	   	if(dis[v]>dis[p]+w[u]*mid-a[p]){//最短路 
		    	dis[v]=dis[p]+w[u]*mid-a[p];//更新 
		      	if(!vis[v]){//没有经过过 
		  			sum[v]++;//边数++ 
					vis[v]=1;//标记已经经过 
					q.push(v);//点放入堆中 
	 	 	    	if(sum[v]>=n) return 1;//有负环 ε=(′ο`*))) 
		    	}
	    	}
	  	}
	}
	return 0;//没得负环\(^o^)/~ 
} 
bool check(double mid){ 
	for(int i=1;i<=n;i++) {
		if(spfa(i)) return 1;//有负环 
	}
	return 0;//无负环 
}
double solve(){
	double l=0.0,r=100.0;
	while(r-l>=1e-3){//避免精度误差,相当于l<=r 
		mid=(l+r)/2;
	  	if(check(mid)) l=mid;//case 1 :<0(有负环)
	  	else r=mid;//case 2:>=0(有负环) 
	}
	return l;//返回答案O(∩_∩)O 
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) {
		scanf("%lf",&a[i]);//输入 
	}
	for(int i=1;i<=m;i++){ 
		scanf("%d%d%d",&x,&y,&z);
	  	add(x,y,z);//建边 
	}
	printf("%.2lf",solve());//答案出来啦(^-^)V 
	return 0;
}

完结撒花❀
✿✿ヽ(°▽°)ノ✿

标签:return,int,题解,USACO2007DEC,样例,负环,vis,Cows,dis
来源: https://www.cnblogs.com/Aurora1217/p/16365530.html