zoukankan      html  css  js  c++  java
  • 20140710 loop

    此题说多了都是泪,明明知道SPFA能找负环,却偏偏用了DFS

    SPFA调试成功

     1 #include<cstdio>
     2 #include<vector>
     3 #include<queue>
     4 #include<memory.h>
     5 #define MAXV 600
     6 #define INF 0x3f3f3f3f
     7  
     8 using std::vector;
     9 using std::queue;
    10  
    11 struct Edge{
    12     double v; 
    13     int to; 
    14 };
    15  
    16 vector<Edge> e[MAXV]; 
    17 double dist[MAXV]; 
    18 int cnt[MAXV]; 
    19 queue<int> buff; 
    20 bool done[MAXV]; 
    21 int V; //节点数
    22 int E; //边数
    23  
    24 bool spfa(double k){ //返回值:TRUE为找到最短路返回,FALSE表示出现负环退出
    25     memset(cnt,0,sizeof(cnt));
    26     memset(done,0,sizeof(done));
    27     for(int i=0;i<V;i++){ //初始化:将除了原点st的距离外的所有点到st的距离均赋上一个极大值
    28         dist[i]=INF; //非原点距离无穷大
    29     }
    30     dist[0]=0;
    31     buff.push(0); //原点入队
    32     done[0]=1; //标记原点已经入队
    33     cnt[0]=1; //修改入队次数为1
    34     while(!buff.empty()){ //队列非空,需要继续松弛
    35         int tmp=buff.front(); //取出队首元素
    36         for(int i=0;i<(int)e[tmp].size();i++){ //枚举该边连接的每一条边
    37             Edge *t=&e[tmp][i]; //由于vector的寻址速度较慢,故在此进行一次优化
    38             if(dist[tmp]+(*t).v-k<dist[(*t).to]){ //更改后距离更短,进行松弛操作
    39                 dist[(*t).to]=dist[tmp]+(*t).v-k; //更改边权值
    40                 if(!done[(*t).to]){ //没有入队,则将其入队
    41                     buff.push((*t).to); //将节点压入队列
    42                     done[(*t).to]=1; //标记节点已经入队
    43                     cnt[(*t).to]+=1; //节点入队次数自增
    44                     if(cnt[(*t).to]>V){ //已经超过V次,出现负环
    45                         while(!buff.empty())buff.pop(); //清空队列,释放内存
    46                         return false; //返回FALSE
    47                     }
    48                 }
    49             }
    50         }
    51         buff.pop();//弹出队首节点
    52         done[tmp]=0;//将队首节点标记为未入队
    53     }
    54     return true; //返回TRUE
    55 } //算法结束
    56  
    57 int main(){ //主函数
    58     scanf("%d%d",&V,&E); //读入点数和边数
    59     for(int i=0,x,y;i<E;i++){
    60         double l;
    61         scanf("%d%d%lf",&x,&y,&l); //读入x,y,l表示从x->y有一条有向边长度为l
    62         x--,y--;
    63         Edge tmp; //设置一个临时变量,以便存入vector
    64         tmp.v=l; //设置边权
    65         tmp.to=y; //设置连接节点
    66         e[x].push_back(tmp); //将这条边压入x的表中
    67     }
    68     double l=0,r=1e+9,mid=(l+r)/2;
    69     for(int i=1;i<=100;i++) {
    70         if(spfa(mid)) l=mid;
    71         else r=mid;
    72         mid=(l+r)/2;
    73     }
    74     printf("%.2lf
    ",mid);
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    【搞笑】各种程序评测结果
    【UVA】P1510 Neon Sign
    【转载】实用:根号怎么打出来? <引自百度>
    【转载】C++中的模板template <typename T>
    * ! THUSC2017杜老师
    * ! THUSCH2017巧克力
    ! BJOI2019光线
    ! BJOI2019奥术神杖
    ! TJOI/HEOI2016字符串
    ! TJOI/HEOI2016求和
  • 原文地址:https://www.cnblogs.com/woshizyj/p/3836475.html
Copyright © 2011-2022 走看看