标签:return int 题解 USACO2007DEC 样例 负环 vis Cows dis
题目大意
给定一张图,边上有花费,点上有收益,点可以多次经过,但是收益不叠加,边也可以多次经过,但是费用叠加。求一个环使得收益和/花费和最大,输出这个比值。
样例
样例输入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
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。