Poj--3621(Spfa,01分数规划)

2014-11-20 23:44:00

思路:构建分数规划函数:d[i] = a[i] - L * b[i],二分L,在图里找环,发现只要找到一个正环,那么L就可以更大。然后发现Spfa可以判图中负环,注意是负环。。。

  于是我们把规划函数变通一下:D[i] = L * b[i] - a[i],那么转化为只要发现负环就能向上更新L,精度不能过高,不然会T。

  1 /*************************************************************************
  2     > File Name: 3621.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com 
  5     > Created Time: Thu 20 Nov 2014 11:14:29 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <map>
 14 #include <set>
 15 #include <stack>
 16 #include <queue>
 17 #include <iostream>
 18 #include <algorithm>
 19 using namespace std;
 20 #define lp (p << 1)
 21 #define rp (p << 1|1)
 22 #define getmid(l,r) (l + (r - l) / 2)
 23 #define MP(a,b) make_pair(a,b)
 24 typedef long long ll;
 25 const int INF = 1 << 30;
 26 const int maxn = 1010;
 27 const int Maxn = 5010;
 28 const double eps = 1e-3;
 29 
 30 int n,m;
 31 int first[maxn],next[Maxn],ver[Maxn],T[Maxn],ecnt;
 32 double F[maxn];
 33 double d[maxn];
 34 int inq[maxn],cnt[maxn];
 35 queue<int> Q;
 36 
 37 void Init(){
 38     memset(first,-1,sizeof(first));
 39     ecnt = 0;
 40 }
 41 
 42 void Add_edge(int u,int v,int t){
 43     next[++ecnt] = first[u];
 44     ver[ecnt] = v;
 45     T[ecnt] = t;
 46     first[u] = ecnt;
 47 }
 48 
 49 bool Spfa(double val){
 50     memset(cnt,0,sizeof(cnt));
 51     memset(inq,0,sizeof(inq));
 52     while(!Q.empty()) Q.pop();
 53     for(int i = 1; i <= n; ++i) d[i] = INF;
 54     d[1] = -F[1];
 55     inq[1] = 1;
 56     cnt[1] = 1;
 57     Q.push(1);
 58     while(!Q.empty()){
 59         int x = Q.front();
 60         Q.pop();
 61         inq[x] = 0;
 62         for(int i = first[x]; i != -1; i = next[i]){
 63             int v = ver[i];
 64             int t = T[i];
 65             double tmp = d[x] + val * t - F[v];
 66             if(d[v] > tmp){
 67                 d[v] = tmp;
 68                 if(!inq[v]){
 69                     inq[v] = 1;
 70                     cnt[v]++;
 71                     if(cnt[v] > n) return true;
 72                     Q.push(v);
 73                 }
 74             }
 75         }
 76     }        
 77     return false;
 78 }
 79 
 80 int main(){
 81     int a,b,c;
 82     while(scanf("%d%d",&n,&m) != EOF){
 83         Init();
 84         for(int i = 1; i <= n; ++i){
 85             scanf("%lf",&F[i]);
 86         }
 87         for(int i = 1; i <= m; ++i){
 88             scanf("%d%d%d",&a,&b,&c);
 89             Add_edge(a,b,c);
 90         }
 91         double low = 0,high = 1000.0;
 92         while(fabs(high - low) > eps){
 93             double mid = getmid(low,high);
 94             if(Spfa(mid))
 95                 low = mid;
 96             else
 97                 high = mid;
 98         }
 99         printf("%.2f\n",low);
100     }
101     return 0;
102 }

 

posted @ 2014-11-20 23:56  Naturain  阅读(176)  评论(0)    收藏  举报