博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UVA 11090 Going in Cycle!! SPFA判断负环+二分
阅读量:5079 次
发布时间:2019-06-12

本文共 2680 字,大约阅读时间需要 8 分钟。

题目链接:

题意:

给你一个有向图,问你定义一个环的平均值为这个环上所有边的平均值,问你最小的环的平均值是多少

题解:

二分答案:若当前的二分值是mid,让所有的边都减去这个值,如果此时图中出现负环,则说明有环的平均值比这个更小

假设一个包含k条边的回路,回路上各条边的权值为w1,w2……wk,那么平均值小于mid意味着 w1+w2+……wk< k* mid即:

(w1-mid)+(w2-mid)+……(wk-mid)<0
有负环,当前平均值就大了

注意图可能不连通,每个没访问过得点都spfa判一遍

代码:

1 #include 
2 using namespace std; 3 typedef long long ll; 4 #define MS(a) memset(a,0,sizeof(a)) 5 #define MP make_pair 6 #define PB push_back 7 const int INF = 0x3f3f3f3f; 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 9 inline ll read(){10 ll x=0,f=1;char ch=getchar();11 while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;ch=getchar();}12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}13 return x*f;14 }15 //16 const int maxn = 50+10;17 double eps = 1e-6;18 19 int n,m;20 21 vector
> G[maxn];22 int vis[maxn],inq[maxn],cnt[maxn];23 double d[maxn];24 25 bool spfa(int u){26 MS(inq);MS(cnt);27 for(int i=0; i<=n; i++) d[i] = INF;28 queue
q;29 q.push(u),inq[u]=1,d[u]=0;30 while(!q.empty()){31 int now = q.front(); q.pop(); inq[now] = 0;32 vis[now] = 1;33 for(int i=0; i<(int)G[now].size(); i++){34 int v = G[now][i].first; double w = G[now][i].second;35 if(d[v] > d[now]+w){36 d[v] = d[now]+w;37 if(inq[v]) continue;38 inq[v] = 1;39 q.push(v);40 cnt[v]++;41 if(cnt[v] > n) return true;42 }43 }44 }45 return false;46 }47 48 bool check(double x){49 for(int i=1; i<=n; i++)50 for(int j=0; j<(int)G[i].size(); j++)51 G[i][j].second -= x; // 让所有的边都减去mid,如果此时图中出现负环,则说明有环的平均值比这个更小52 MS(vis);53 bool flag;54 for(int i=1; i<=n; i++){55 if(!vis[i]) // 图可能不连通,每个没访问过得点都判一遍56 flag = spfa(i);57 if(flag) break;58 }59 60 for(int i=1; i<=n; i++)61 for(int j=0; j<(int)G[i].size(); j++)62 G[i][j].second += x;63 64 return flag; // flag为true 就是有负环,当前平均值就大了65 }66 67 68 int main(){69 int T = read();70 for(int cas=1; cas<=T; cas++){71 for (int i = 0; i <= n; i++)G[i].clear();72 scanf("%d%d",&n,&m);73 for(int i=1; i<=m; i++){74 int u,v; double w;75 scanf("%d%d%lf",&u,&v,&w);76 G[u].push_back(MP(v,w));77 }78 79 double L=0,R=1e7,ans=1e7;80 while((R-L)>eps){81 double mid = (L+R)/2;82 if(check(mid)) ans=mid,R=mid-eps;83 else L=mid+eps;84 }85 if(abs(ans-1e7)

 

转载于:https://www.cnblogs.com/yxg123123/p/6827625.html

你可能感兴趣的文章
SSID、BSSID、BSS等区分
查看>>
unittest学习3:用例执行
查看>>
Jmeter_1:安装、汉化
查看>>
C++ 泛型
查看>>
C++队列
查看>>
初次尝试python爬虫,爬取小说网站的小说。
查看>>
vue-cli脚手架build目录下utils.js工具配置文件详解
查看>>
switch支持的数据类型
查看>>
通过Eureka自带REST API强行剔除失效服务
查看>>
C++11 lambda表达式是如何实现的?
查看>>
pthread_rwlock
查看>>
《springMVC》学习笔记
查看>>
第一章 Bootstrap简介
查看>>
C++ 宏定义创建(销毁)单例
查看>>
Java实现各种排序
查看>>
播放背景音乐
查看>>
Android 中关于draw中图片分辨率的说明
查看>>
数据库备份启用加密
查看>>
直线运动
查看>>
理解HTTP session原理及应用(转)
查看>>