uva11090 Bellman-Ford 运用

给定一一个n个点m条边的加权有向图, 平均值最小的回路。

二分答案,对于每个二分的mid 做一次Bellman-Fprd , 假设有k条边组成的回路。 回路上各条边的权值为  w1 , w2 ..wk ,

那么平均值小于mid意味着w1+w2+w3..+wk< k*mid 即:

(w1 - min)+(w2-mid)+...+(w2-mid)<0;

也就是说 这k条边能组成 一个负环,用 Bellman_Ford 来检查

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <string.h>
  5 #include <vector>
  6 #include <queue>
  7 #include <cmath>
  8 using namespace std;
  9 const int maxn = 55;
 10 int cmp(double a ,double b){
 11      if(fabs(a-b)<=0.00000001) return 0;
 12      return a-b>0?1:-1;
 13 }
 14 struct Edge{
 15    int from,to;
 16    double dist;
 17 };
 18 struct BellmanFord{
 19     int n,m;
 20     vector<Edge> edges;
 21      vector<int> G[maxn];
 22      bool inq[maxn];
 23      double d[maxn];
 24      int p[maxn];
 25      int cnt[maxn];
 26      void inti(int n){
 27          m=0;
 28         this->n = n;
 29         for(int i=0; i<n; ++i ) G[i].clear();
 30         edges.clear();
 31      }
 32      void AddEdge(int form, int to, double dist){
 33         edges.push_back((Edge){form,to,dist});
 34         m =edges.size();
 35         G[form].push_back(m-1);
 36      }
 37      bool negativeCycle(){
 38          queue<int> Q;
 39          memset(inq, 0, sizeof(inq));
 40          memset(cnt, 0, sizeof(cnt));
 41          for(int i=0; i < n; ++i)  {  d[i] =0; inq[i] = true; Q.push(i);}
 42          while(!Q.empty()){
 43             int u = Q.front(); Q.pop();
 44             inq[u] = false;
 45             for(int i=0; i<G[u].size(); i++){
 46                 Edge &e = edges[G[u][i]];
 47                 if(cmp(d[e.to] , d[u] + e.dist)>0){
 48                      d[e.to] = d[u] +e.dist;
 49                      p[e.to] = G[u][i];
 50                      if(!inq[e.to]){
 51                          Q.push(e.to); inq[e.to] = true;
 52                          if(++cnt[e.to]>n) return true;
 53                      }
 54                 }
 55             }
 56          }
 57          return false;
 58      }
 59 }solver;
 60 bool test(double x){
 61      for(int i=0; i<solver.m; i++){
 62         solver.edges[i].dist-=x;
 63      }
 64      bool ret = solver.negativeCycle();
 65      for(int i= 0; i<solver.m; i++)
 66          solver.edges[i].dist+=x;
 67      return ret;
 68 }
 69 int main()
 70 {
 71    int T;
 72    scanf("%d",&T);
 73    for(int kase =1; kase<=T; kase++){
 74        int n,m;
 75        scanf("%d%d",&n,&m);
 76        solver.inti(n);
 77        int ub =0;
 78        while(m--){
 79           int u,v,w;
 80           scanf("%d%d%d",&u,&v,&w); u--,v--; ub= max(ub,w);
 81           solver.AddEdge(u,v,w);
 82        }
 83        printf("Case #%d: ",kase);
 84        double ans = ub;
 85        if(!test(ub+1)){
 86          printf("No cycle found.\n");
 87        }else{
 88             double L =0,R= ub;
 89             while(R-L>1e-3){
 90                 double M = L+(R-L)/2;
 91                 if(test(M)){
 92                         R=M;
 93                 }else {
 94                     L=M;
 95                 }
 96             }
 97             printf("%.2lf\n",L);
 98        }
 99
100    }
101     return 0;
102 }
时间: 2024-10-10 14:31:59

uva11090 Bellman-Ford 运用的相关文章

ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)

两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可以求得一点到任意一点经过一条边的最短路,遍历两次可以求得一点到任意一点经过两条边的最短路...如 此反复,当遍历m次所有边后,则可以求得一点到任意一点经过m条边后的最短路(有点类似离散数学中邻接矩阵的连通性判定) POJ1556-The Doors 初学就先看POJ2240吧 题意:求从(0,5)到

POJ 1860 Currency Exchange (Bellman ford)

Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22405   Accepted: 8095 Description Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and pe

Bellman - Ford 算法解决最短路径问题

Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力不从心了,而Bellman - Ford算法可以解决这种问题. Bellman - Ford 算法可以处理路径权值为负数时的单源最短路径问题.设想可以从图中找到一个环路且这个环路中所有路径的权值之和为负.那么通过这个环路,环路中任意两点的最短路径就可以无穷小下去.如果不处理这个负环路,程序就会永远运

Bellman—Ford算法思想

---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G运行Bellman—Ford算法的结果是一个布尔值,表明图中是否存在着一个从源点s可达的负权回路.若存在负权回路,单源点最短路径问题无解:若不存在这样的回路,算法将给出从源点s到图G的任意顶点v的最短路径值d[v] Bellman—Ford算法流程 分为三个阶段: (1)初始化:将除源点外的所有顶点

ACM/ICPC 之 Bellman Ford练习题(ZOJ1791(POJ1613))

这道题稍复杂一些,需要掌握字符串输入的处理+限制了可以行走的时间. ZOJ1791(POJ1613)-Cave Raider //限制行走时间的最短路 //POJ1613-ZOJ1791 //Time:16Ms Memory:324K #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; #define MAX 505 #d

poj 3259 Wormholes (BELLman—FOrd算法)(邻接矩阵表示)

http://poj.org/problem?id=3259 之前一开始 ,没做出来,搁置了好几天才看见bug所在.所以今天a掉了 ,把代码贴出来,这个使用邻接矩阵表示的 ,下一篇用邻接表可以提高效率. #include<iostream> #include<queue> #include<stdio.h> #include<string.h> using namespace std; const int INF=600; int G[INF][INF];

Bellman ford 最短路径算法

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" /> 下表记录S到每一个节点的距离: 第一次迭代, S->A = 4 ,由于S->A眼下为INF.因此更新MIN(S->A)为4 S->B = 6.由于S->B眼下为INF.因此更新MIN(S->B)为6 S->C

最短路径——Bellman Ford算法(C++)

源代码: #include<cstdio>#include<cstring>int m(1),n,k,i[1001],x[1001],y[1001],f[1001];int main(){ scanf("%d%d",&n,&k); for (int a=1;a<=n;a++) for (int b=1;b<=n;b++) { scanf("%d",&i[m]); if (i[m]!=-1) { x[m]=a

poj3259 bellman——ford Wormholes解绝负权问题

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 35103   Accepted: 12805 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way p

PKU 3169 Layout(差分约束系统+Bellman Ford)

题目大意:原题链接 当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些.FJ有N(2<=N<=1000)头奶牛,编号从1到N,沿一条直线站着等候喂食.奶牛排在队伍中的顺序和它们的编号是相同的.因为奶牛相当苗条,所以可能有两头或者更多奶牛站在同一位置上(即间距可能为0).即是说,如果我们想象奶牛是站在一条数轴上的话,允许有两头或更多奶牛拥有相同的横坐标. 一些奶牛相互间存有好感,它们希望两者之间的距离不超过一个给定的数L.另一方面,一些奶牛相互间非常反感,它们希望两者间的距离不小于一个给定的数D.