分析:
其实就分数规划来讲这道题很简单….
重点是判负环…
一般的spfa判负环一定会TLE,看看数据范围就知道了…
怎么办呢…可以dfs判负环,但是还是会TLE…
怎么办啊…
有一个机智的办法,反正我们都是判负环,为什么还要把dis赋成inf呢,干脆赋成0好了…正确是显然的…时间复杂度呢…递归层数减少了…只有变成负数的时候才会去递归…所以从10sTLE变成了128msAC…
代码如下:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
//by NeighThorn
#define inf 100000000000
using namespace std;
//长眉连娟,微睇绵藐,色授魂与,心愉于侧
const int maxn=3000+5,maxm=10000+5;
int n,m,hd[maxn],to[maxm],nxt[maxm],vis[maxn],tim[maxn],cnt;
double w[maxm],sum,dis[maxn];
inline void add(double s,int x,int y){
w[cnt]=s;to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
}
inline bool dfs(int root,double mid){
vis[root]=1;
for(int i=hd[root];i!=-1;i=nxt[i])
if(dis[to[i]]>dis[root]+w[i]-mid){
if(vis[to[i]])
return true;
dis[to[i]]=dis[root]+w[i]-mid;
if(dfs(to[i],mid))
return true;
}
vis[root]=0;
return false;
}
inline bool check(double mid){
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
for(int i=1;i<=n;i++)
if(dfs(i,mid))
return true;
return false;
}
signed main(void){
memset(hd,-1,sizeof(hd));
scanf("%d%d",&n,&m);
double s;cnt=sum=0;
for(int i=1,x,y;i<=m;i++)
scanf("%d%d%lf",&x,&y,&s),add(s,x,y),sum+=s;
double l=-inf,r=inf,ans;
while(r-l>=1e-9){
double mid=(l+r)/2.0;
if(check(mid))
r=mid,ans=mid;
else
l=mid;
}
printf("%.8f\n",ans);
return 0;
}
by >_< NeighThorn