codevs 1183 泥泞的道路 (二分+SPFA+差分约束)
/* 二分答案(注意精度) 对于每一个答案 有(s1+s2+s3...)/(t1+t2+t3...)>=ans 时符合条件 这时ans有变大的空间 对于上述不等式如果枚举每一条路显得太暴力 化简一下变成 :s1-t1*ans+s2-t2*ans+s3-t3*ans...>=0 差分约束跑最长路 如果dis[n]>0 或者有正环 (开始这个忘掉了)ans就合法 */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> const double Jing=0.0001; using namespace std; double s[110][110],t[110][110],ans,a[110][110],dis[110]; int n,f[110],c[110],falg; void SPFA(int st) { memset(f,0,sizeof(f)); memset(dis,-0x3f,sizeof(dis)); queue<int>q; q.push(st);f[st]=1;dis[st]=0,c[st]=1; while(!q.empty()) { int k=q.front(); q.pop(); if(c[k]>n) { falg=1;break; } for(int i=1;i<=n;i++) if(s[k][i]&&dis[i]<dis[k]+a[k][i]) { dis[i]=dis[k]+a[k][i]; if(f[i]==0) { c[i]=c[k]+1; q.push(i); f[i]=1; } } f[k]=0; } } bool check(double x) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=s[i][j]-x*t[i][j]; falg=0; SPFA(1); if(dis[n]>0||falg==1)return 1; else return 0; } int main() { cin>>n; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>s[i][j]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>t[i][j]; double l=0,r=100; while(r-l>Jing) { double mid=(l+r)/2; if(check(mid)) { ans=mid; l=mid; } else r=mid; } printf("%.3f",ans); return 0; }