http://poj.org/problem?id=3621
01规划,二分答案,重组边权,SPFA判负环。
code:
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 const int N=1000+10; 6 const int M=5000+10; 7 const double INF=1e10; 8 int head[N],ver[M],from[M],nex[M],T[M],F[M],tot=0; 9 double edge[M]; 10 inline void add(int x,int y,int t,int f) 11 { 12 ver[++tot]=y; 13 from[tot]=x; 14 T[tot]=t; 15 F[tot]=f; 16 nex[tot]=head[x]; 17 head[x]=tot; 18 } 19 20 int n,m; 21 int fun[N]; 22 23 bool vis[N]; 24 double dis[N]; 25 int cnt[N]; 26 27 bool judge(double mi) 28 { 29 memset(vis,0,sizeof(vis)); 30 cnt[1]=0; 31 for(int i=1;i<=tot;++i) 32 edge[i]=mi*T[i]-F[i]; 33 for(int i=1;i<=n;++i) 34 dis[i]=INF; 35 dis[1]=0; 36 vis[1]=1; 37 queue<int> q; 38 q.push(1); 39 40 while(!q.empty()) 41 { 42 int x=q.front(); 43 q.pop(); 44 vis[x]=0; 45 for(int i=head[x];i;i=nex[i]) 46 { 47 int y=ver[i]; 48 if(dis[y]>dis[x]+edge[i]) 49 { 50 dis[y]=dis[x]+edge[i]; 51 cnt[y]=cnt[x]+1; 52 if(cnt[y]>=n) 53 return true; 54 if(vis[y])continue; 55 vis[y]=1; 56 q.push(y); 57 } 58 } 59 } 60 return false; 61 } 62 63 double eps=1e-8; 64 void solve() 65 { 66 double l=0,r=1100; 67 while(r-l>eps) 68 { 69 double m=(l+r)/2; 70 if(judge(m)) 71 l=m; 72 else r=m; 73 } 74 if(l<eps) 75 puts("0"); 76 else printf("%.2f\n",l); 77 } 78 79 int main() 80 { 81 scanf("%d%d",&n,&m); 82 for(int i=1;i<=n;++i) 83 scanf("%d",fun+i); 84 for(int i=0;i<m;++i) 85 { 86 int x,y,t; 87 scanf("%d%d%d",&x,&y,&t); 88 add(x,y,t,fun[x]); 89 } 90 solve(); 91 return 0; 92 }