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 }

浙公网安备 33010602011771号