UVA 11090 - Going in Cycle!! SPFA
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2031
题目大意:
给定一个n个点m条边的加权有向图,求平均权值最小的回路。
思路:
用二分法求解。假设答案为mid,只需要判断是否存在平均值小于Mid的回路。怎么判断呢?假设一个包含k条边的回路,回路上各条边的权值为w1,w2……wk,那么平均值小于mid意味着 w1+w2+……wk< k* mid即:
(w1-mid)+(w2-mid)+……(wk-mid)<0
换句话说,只要把图中没一条边a,b的权值w(a,b)变为w(a,b)-mid,在判断图中有没有负权回路。
怎么判断负权回路呢?这就是SPFA的用法了,一个顶点入队列超过n次,就表示有回路。
记住这个不一定是联通的图。所以一开始要把所有的点加入队列。WA找了半天看了别人代码才发现。
---------------2014/01/26----------
想起可以增加一个点0,从该点到所有点的权值为0,那么可以保证改图连通,并且不会破坏负环~~~~~~
代码如下:
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=52;
const int INF=100000000;
struct edge
{
int to;
double val;
int next;
}e[MAXN*MAXN]; int head[MAXN],len,n,m;
void add(int from,int to,double val)
{
e[len].to=to;
e[len].val=val;
e[len].next=head[from];
head[from]=len++;
} bool spfa()
{
double dis[MAXN];
bool vis[MAXN]={0};
int cnt[MAXN]={0};
queue<int> q;
for(int i=1;i<=n;i++) //图可能是非联通的,所以一开始要把全部加入。WA在这里
dis[i]=INF; q.push(0);
vis[0]=cnt[0]=1;
dis[0]=0; while(!q.empty())
{
int cur=q.front();
q.pop();
vis[cur]=false;
for(int i=head[cur];i!=-1;i=e[i].next)
{
int id=e[i].to;
if(dis[cur] + e[i].val < dis[id])
{
dis[id]=dis[cur]+e[i].val;
if(!vis[id])
{
cnt[id]++;
vis[id]=true;
q.push(id);
if(cnt[cur] > n)
return true;
}
}
}
}
return false;
} void change(double x)
{
for(int k=1;k<=n;k++)
for(int i=head[k];i!=-1;i=e[i].next)
e[i].val+=x;
}
bool test(double x)
{
change(-x);
bool ok=spfa();
change(x);
return ok;
} int main()
{
int T;
scanf("%d",&T);
for(int ri=1;ri<=T;ri++)
{
len=0;
memset(head,-1,sizeof(head));
double L=INF,R=0;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int from,to;
double val;
scanf("%d%d%lf",&from,&to,&val);
if(R< val)
R=val;
if(L > val)
L=val;
add(from,to,val);
}
for(int i=1;i<=n;i++)
add(0,i,0); printf("Case #%d: ",ri);
if(!test(R+1))
{
printf("No cycle found.\n");
continue;
} while(R-L > 1e-3) //浮点数判断大小要这样
{
double mid = L + (R-L)/2;
if(test(mid))
R = mid;
else
L = mid;
}
printf("%.2lf\n",R);
} return 0;
}
一开始全部加入队列版本
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=52;
const int INF=100000000;
struct edge
{
int to;
double val;
int next;
}e[MAXN*MAXN]; int head[MAXN],len,n,m;
void add(int from,int to,double val)
{
e[len].to=to;
e[len].val=val;
e[len].next=head[from];
head[from]=len++;
} bool spfa()
{
double dis[MAXN];
bool vis[MAXN];
int cnt[MAXN];
queue<int> q;
for(int i=1;i<=n;i++) //图可能是非联通的,所以一开始要把全部加入。WA在这里
{
dis[i]=INF;
vis[i]=true;
cnt[i]=1;
q.push(i);
} while(!q.empty())
{
int cur=q.front();
q.pop();
vis[cur]=false; for(int i=head[cur];i!=-1;i=e[i].next)
{
int id=e[i].to;
if(dis[cur] + e[i].val < dis[id])
{
dis[id]=dis[cur]+e[i].val;
if(!vis[id])
{
cnt[id]++;
vis[id]=true;
q.push(id);
if(cnt[cur] > n)
return true;
}
}
}
}
return false;
} void change(double x)
{
for(int k=1;k<=n;k++)
for(int i=head[k];i!=-1;i=e[i].next)
e[i].val+=x;
}
bool test(double x)
{
change(-x);
bool ok=spfa();
change(x);
return ok;
} int main()
{
int T;
scanf("%d",&T);
for(int ri=1;ri<=T;ri++)
{
len=0;
memset(head,-1,sizeof(head));
double L=INF,R=0;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int from,to;
double val;
scanf("%d%d%lf",&from,&to,&val);
if(R< val)
R=val;
if(L > val)
L=val;
add(from,to,val);
}
printf("Case #%d: ",ri);
if(!test(R+1))
{
printf("No cycle found.\n");
continue;
} while(R-L > 1e-3) //浮点数判断大小要这样
{
double mid = L + (R-L)/2;
if(test(mid))
R = mid;
else
L = mid;
}
printf("%.2lf\n",R);
} return 0;
}
UVA 11090 - Going in Cycle!! SPFA的更多相关文章
- UVA 11090 Going in Cycle!! SPFA判断负环+二分
原题链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- UVA - 11090 - Going in Cycle!!(二分+差分约束系统)
Problem UVA - 11090 - Going in Cycle!! Time Limit: 3000 mSec Problem Description You are given a we ...
- UVA 11090 - Going in Cycle!!(Bellman-Ford)
UVA 11090 - Going in Cycle!! option=com_onlinejudge&Itemid=8&page=show_problem&category= ...
- UVA 11090 Going in Cycle!! 环平均权值(bellman-ford,spfa,二分)
题意: 给定一个n个点m条边的带权有向图,求平均权值最小的回路的平均权值? 思路: 首先,图中得有环的存在才有解,其次再解决这个最小平均权值为多少.一般这种就是二分猜平均权值了,因为环在哪也难以找出来 ...
- UVA 11090 : Going in Cycle!! 【spfa】
题目链接 题意及题解参见lrj训练指南 #include<bits/stdc++.h> using namespace std; const double INF=1e18; ; ; in ...
- UVa 11090 Going in Cycle!!【Bellman_Ford】
题意:给出n个点m条边的加权有向图,求平均值最小的回路 自己想的是用DFS找环(真是too young),在比较找到各个环的平均权值,可是代码实现不了,觉得又不太对 后来看书= =好巧妙的办法, 使用 ...
- UVA 11090 Going in Cycle!!(二分答案+判负环)
在加权有向图中求平均权值最小的回路. 一上手没有思路,看到“回路”,第一想法就是找连通分量,可又是加权图,没什么好思路,那就转换题意:由求回路权值->判负环,求最小值->常用二分答案. 二 ...
- UVA 11090 Going in Cycle!!
要求给定的图的中平均权值最小的环,注意处理自环的情况就能过了. 按照w1+w2+w3+….wn < n*ave的不等式,也就是(w1-ave) + (w2-ave) +…..(wn-ave) & ...
- UVa 11090 Going in Cycle!! (Bellman_Ford)
题意:给定一个加权有向图,求平均权值最小的回路. 析:先十分答案,假设答案是 ans,那么有这么一个回路,w1+w2+w3+...+wk < k*ans,这样就是答案太大,然后移项可得,(w1- ...
随机推荐
- hdu 1875 畅通project再续(kruskal算法计算最小生成树)
畅通project再续 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- [BZOJ3566][SHOI2014]概率充电器 换根树形DP
链接 题意:n个充电元件形成一棵树,每个点和每条边都有各自的充电概率,元件可以自身充电或者通过其他点和边间接充电,求充电状态元件的期望个数 题解 设1为根节点 设 \(f[x]\) 表示 \(x\) ...
- FormData是什么
FormData是什么 一.总结 一句话总结:利用 FormData 对象,可以通过JavaScript键值对来模拟一系列表单控件,还可以使用 XMLHttpRequest的send() 方法来异步提 ...
- storm单机运行与集群运行问题
使用trident接口时,storm读取kafka数据会将kafka消费记录保存起来,将消费记录的位置保存在tridentTopology.newStream()的第一个参数里, 如果设置成从头开始消 ...
- Windows学习总结(2)——30+ Windows命令提示符快捷键汇总
即便你平时经常用到 Windows 命令提示符,可能也会对本文将提到的快捷键数量感到惊讶.其实我们可以使用快捷键来简化命令提示符中的选择操作,或对文本进行重复操作,下面我们会列出完整列表. 大家都知道 ...
- [TypeScript] Shallow copy object by using spread opreator
For example we have an object: const todo = { text: "Water the flowers", completed: false, ...
- cocoapod卡在了analyzing dependencies
尽管公司的项目没有使用cocoapod,可是有一些第三方库本身依赖其它第三方的库,而且是用cocoapod来管理这些依赖的.所以在使用某些第三方库时.还是须要用到cocoapod的.今天在github ...
- Android 使用AIDL实现进程间的通信
在Android中,如果我们需要在不同进程间实现通信,就需要用到AIDL技术去完成. AIDL(android Interface Definition Language)是一种接口定义语言,编译器通 ...
- 反序列化xml到treeview
private void Form1_Load(object sender, EventArgs e) { string xmlPath = System.Environment.CurrentDir ...
- 【2017中国大学生程序设计竞赛 - 网络选拔赛】A Secret
[链接]http://acm.hdu.edu.cn/showproblem.php?pid=6153 [题意] ,S2中出现的次数与其长度的乘积之和. [题解] 扩展KMP的模板题. 首先,把S2和 ...