BZOJ 1486 [HNOI2009] 最小圈

来源:互联网 发布:c语言结构体 编辑:程序博客网 时间:2024/05/02 01:03

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

HINT

Source

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

01分数规划+dfs/SPFA判负环~

根据01分数规划,我们二分寻找能使sum{(a[i]-b[i]*k)*x[i]}==0的k值,然后判负环,如果有负环,就增大k值。

注意这道题卡SPFA判负环,只能用类似于dfs+SPFA的判断方法,详见代码~


#include<cstdio>#include<cstring>#include<iostream>using namespace std;#define eps 1e-10int n,m,x,y,fi[3001],w[20001],ne[20001],cnt;bool b[3001];double z,v[20001],ll[20001],mid,dis[3001];void add(int u,int vv,double val){w[++cnt]=vv;ne[cnt]=fi[u];fi[u]=cnt;v[cnt]=val;}bool dfs(int u){b[u]=1;for(int i=fi[u];i;i=ne[i])  if(dis[w[i]]>ll[i]+dis[u])  {if(b[w[i]]){b[u]=0;return 1;}dis[w[i]]=ll[i]+dis[u];if(dfs(w[i])){b[u]=0;return 1;}  }b[u]=0;return 0;}bool che(){memset(dis,0,sizeof(dis));for(int i=1;i<=cnt;i++) ll[i]=v[i]-mid;for(int i=1;i<=n;i++) if(dfs(i)) return 1;return 0; }int read(){int totnum=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {totnum=(totnum<<1)+(totnum<<3)+ch-'0';ch=getchar();}return totnum*f; }int main(){n=read();m=read();for(int i=1;i<=m;i++) x=read(),y=read(),scanf("%lf",&z),add(x,y,z);double l=-1e7,r=1e7;while(r-l>=eps){mid=(l+r)*1.0/2.0;if(che()) r=mid;else l=mid; }printf("%.8lf\n",mid);return 0;}


1 0
原创粉丝点击