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

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);
}

 

posted @ 2017-05-20 15:15  qt666  阅读(131)  评论(0编辑  收藏  举报