bzoj 1486: [HNOI2009]最小圈
Description
Input
Output
Sample Input
4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
Sample Output
3.66666667
HINT
Source
额...APIO2017极限弱化版...
做法的话直接上分数规划的套路即可,没什么好说的;
二分后,相当判断有没有小于等于0的环,直接spfa判负环即可
但zz选手竟然T了两回,一次因为memset,一次是把进队次数卡的是n!!!(差不多只要100)
#include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #include<cstring> #define RG register using namespace std; typedef long long ll; const int N=1000050; const double eps=1e-9; int gi() { int x=0,flag=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*flag; } struct edge{ int x,y,w; }road[N]; int head[N],nxt[N],to[N],cnt,n,m,vis[N]; double v[N],dis[N]; inline void lnk(RG int x,RG int y,RG double z){ to[++cnt]=y,nxt[cnt]=head[x],v[cnt]=z,head[x]=cnt; } inline bool spfa(RG int x) { for(RG int i=head[x];i;i=nxt[i]) { RG int y=to[i]; if(dis[y]>dis[x]+v[i]) { dis[y]=dis[x]+v[i]; if(vis[y]++>100||spfa(y)) return 1; } } return 0; } int main(){ n=gi(),m=gi(); for(RG int i=1;i<=m;i++){ road[i].x=gi(),road[i].y=gi(),road[i].w=gi(); } double l=-10000000,r=10000000,ans; while(r-l>=eps){ double mid=(l+r)/2;int flag=0; for(int i=1;i<=n;i++) head[i]=0;cnt=1; for(RG int i=1;i<=m;i++) lnk(road[i].x,road[i].y,road[i].w-mid); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) dis[j]=0,vis[j]=0; if(spfa(i)) {flag=1;break;}; } if(flag) r=mid,ans=mid; else l=mid; } printf("%.8f\n",ans); }