【POJ 3621】Sightseeing Cows(最优比例环)
由于一个环上点和边的个数是一样的 所以选了一条边后 点也就知道了
所以有判定函数 F(R)=∑Vi∗Xi−R∗∑Wj∗Xi
怎么判定F(R)的大小呢
按照道理 我们应该用V(u)−R∗W(u,v)来更新dis 有一个正环就可以减小r 但是spfa只能方便的判负环 所以取一下相反数即可
#include<iostream> #include<cstring> #include<iomanip> #include<queue> #define N 1005 #define M 5005 #define eps 1e-6 #define INF 0x7fffffff using namespace std; int n,m,tot,first[N]; double val[N]; struct Node { int to,next; double v; }edge[2*M]; inline void addedge(int x,int y,double z) { tot++; edge[tot].to=y; edge[tot].next=first[x]; edge[tot].v=z; first[x]=tot; } bool inque[N]; int used[N]; double dis[N]; inline bool spfa(double a) { memset(used,0,sizeof(used)); memset(inque,false,sizeof(inque)); queue <int> q; for(int i=1;i<=n;i++) dis[i]=INF; dis[1]=0; q.push(1); inque[1]=true; while(!q.empty()) { int now=q.front(); q.pop(); inque[now]=false; for(int u=first[now];u;u=edge[u].next) { int vis=edge[u].to; if(dis[now]+edge[u].v*a-val[now]<dis[vis]) //这里取了相反数 { dis[vis]=dis[now]+edge[u].v*a-val[now]; if(!inque[vis]) { q.push(vis); inque[vis]=true; used[vis]++; if(used[vis]>n) return true; } } } } return false; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) cin>>val[i]; for(int i=1;i<=m;i++) { int x,y; double z; cin>>x>>y>>z; addedge(x,y,z); } double l=0,r=10000; while(l+eps<r) { double m=(l+r)/2; if(spfa(m)) l=m; else r=m; } cout<<fixed<<setprecision(2)<<l; return 0; }
QQ40523591~欢迎一起学习交流~