POJ-3621 Sightseeing Cows 最优比率环、01分数规划
题目链接:http://poj.org/problem?id=3621
这题是01分数规划问题,详细资料点这里。有了01分数规划的基础后,这个题目就很简单了。构建函数f(mid)=Σ(w[i]-mid*d[i]),然后二分mid,如果图中有正权环,则f(mid)>0,则还有更优解l=mid,否则r=mid。
1 //STATUS:C++_AC_563MS_296KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector> 10 #include<queue> 11 #include<stack> 12 using namespace std; 13 #define LL __int64 14 #define pii pair<int,int> 15 #define Max(a,b) ((a)>(b)?(a):(b)) 16 #define Min(a,b) ((a)<(b)?(a):(b)) 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define lson l,mid,rt<<1 19 #define rson mid+1,r,rt<<1|1 20 const int N=1010,M=1000000,INF=0x3f3f3f3f,MOD=1999997; 21 const LL LLNF=0x3f3f3f3f3f3f3f3fLL; 22 const double DNF=100000000; 23 24 struct Edge{ 25 int u,v,w; 26 }e[5*N]; 27 double d[N]; 28 int w[N],inq[N],first[N],next[5*N],cou[N]; 29 int n,m,mt; 30 31 void adde(int a,int b,int c) 32 { 33 e[mt].u=a,e[mt].v=b,e[mt].w=c; 34 next[mt]=first[a],first[a]=mt++; 35 } 36 37 int SPFA(int s,double mid) 38 { 39 int i,j,u,v; 40 queue<int> q; 41 for(i=1;i<=n;i++)d[i]=-DNF;d[s]=0; 42 mem(inq,0);mem(cou,0); 43 q.push(s); 44 while(!q.empty()){ 45 u=q.front();q.pop(); 46 inq[u]=0; 47 for(i=first[u];i!=-1;i=next[i]){ 48 v=e[i].v; 49 if(d[u]+w[u]-e[i].w*mid>d[v]){ 50 d[v]=d[u]+w[u]-e[i].w*mid; 51 if(!inq[v]){ 52 inq[v]=1; 53 if(++cou[v]==n)return 1; 54 q.push(v); 55 } 56 } 57 } 58 } 59 return 0; 60 } 61 62 double binary() 63 { 64 double l=0,r=1000,mid; 65 while(r-l>1e-3){ 66 mid=l+(r-l)/2; 67 if(SPFA(1,mid)>0)l=mid; 68 else r=mid; 69 } 70 return mid; 71 } 72 73 int main() 74 { 75 // freopen("in.txt","r",stdin); 76 int i,j,a,b,c; 77 while(~scanf("%d%d",&n,&m)) 78 { 79 mt=0; 80 mem(first,-1); 81 for(i=1;i<=n;i++) 82 scanf("%d",&w[i]); 83 for(i=0;i<m;i++){ 84 scanf("%d%d%d",&a,&b,&c); 85 adde(a,b,c); 86 } 87 88 printf("%.2lf\n",binary()); 89 } 90 return 0; 91 }