BZOJ1486: [HNOI2009]最小圈 分数规划

来源:互联网 发布:凡科互动 游戏源码 编辑:程序博客网 时间:2024/05/16 14:38

1486: [HNOI2009]最小圈

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 2065  Solved: 965
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3

Sample Output

3.66666667

题解:0/1分数规划、最优比率生成环:

先二分答案。
因为要判断sigma(wij)/sigma(k)?<=mid
移项一下:sigma(wij)-sigma(k)*mid<=0
sigma(wij-mid*k)<=0;
(k为环中点的个数)
于是我们可以重新构图,把边权转化为wij-k*mid
直接把二分的判断条件转化为是否能找到负环
判断负环的话用dfs比较快,用spfa也可以
#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int N=5005;const int M=10005;int n,m;int cnt,to[M],nxt[M],lj[N];double w[M],p[M];void add(int f,int t,double pp){to[++cnt]=t;nxt[cnt]=lj[f];lj[f]=cnt;w[cnt]=pp;}double d[N];bool used[N],flag;void dfs(int x){used[x]=1;for(int i=lj[x];i;i=nxt[i])if(d[x]+w[i]<d[to[i]]){if(used[to[i]]){flag=1;break;}else {d[to[i]]=d[x]+w[i];dfs(to[i]);}}used[x]=0;}bool judge(double mu){for(int i=1;i<=m;i++) w[i]=p[i]-mu;memset(used,0,sizeof(used));memset(d,0,sizeof(d));flag=0;for(int i=1;i<=n;i++){dfs(i);if(flag) return 1;}return 0;}int main(){scanf("%d%d",&n,&m);int x,y;for(int i=1;i<=m;i++){scanf("%d%d%lf",&x,&y,&p[i]);add(x,y,p[i]);}double l=-1000000,r=1000000,mid,ans=1e9;while(l<r-1e-9){mid=(l+r)/2;if(judge(mid)) r=mid,ans=min(ans,mid);else l=mid;}printf("%.8lf",ans);} 


0 0
原创粉丝点击