POJ-3621-01分数规划,spfa判负环

来源:互联网 发布:js回调函数是闭包吗 编辑:程序博客网 时间:2024/05/22 06:29

题目大意:一张有向图,求一个环的点权和除以边权和,使得那个环在所有环中点权和除以边权和最大。

题目解析:最优比例环,令sigma(vi)/sigma(ei)<=ans,ans*sigma(ei)-sigma(vi)>=0,换句话说如果途中有负环,就不成立,上式成立需要所有换都不是负环,我们只需要二分ans即可;

AC代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<queue>using namespace std;struct Edge{int to,w,next;}edge[5050];int tol,head[1010],n,k,fun[1010];void init(){memset(head,-1,sizeof(head));tol=0;}void addedge(int u,int v,int w){edge[tol].to=v;edge[tol].w=w;edge[tol].next=head[u];head[u]=tol++;}bool spaf(double m){queue<int>q;while(!q.empty())q.pop();int inque[1010],in[1010];double dis[1010];memset(inque,0,sizeof(inque));memset(in,0,sizeof(in));for(int i=1;i<=n;i++){dis[i]=0;inque[i]=1;in[i]=1;q.push(i);}while(!q.empty()){int u = q.front();q.pop();inque[u]=0;for(int i = head[u];i!=-1;i=edge[i].next){int v = edge[i].to;double t = m*edge[i].w-fun[v];if(dis[v]>dis[u]+t){dis[v]=dis[u]+t;if(!inque[v]){inque[v]=1;q.push(v);in[v]++;if(in[v]>n)return true;}}}}return false;}int main(){while(scanf("%d%d",&n,&k)!=EOF){init();for(int i=1;i<=n;i++)scanf("%d",&fun[i]);for(int i=1;i<=k;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);addedge(u,v,w);}double l=0,r=1000;while(r-l>1e-5){double mid=(l+r)/2;if(spaf(mid))l=mid;else r=mid;}printf("%.2f\n",l);}return 0;}




0 0
原创粉丝点击