看到最小平均值,就想到二分之后去判断是否为负数。根据题目,用spfa来判断有无负环,判断的标准为一个点到达过n次以上。
然而有个很严重的bug,现在还没想通,原来我用的是记录最大边长maxlen,然后r=maxlen+1,如果最后ans>maxlen-eps就证明没有路径,结果WA了1小时,看看网上代码,改成r=10000010,ans>10000000就输出没有路劲,最后就A了,这很不科学.......难道ans有可能大于最大边长吗
#include<cstdio>
#include<cstring>
#include<queue>
#define maxl 55
#define inf 2000000001
#define eps 1e-9
using namespace std;
int n,m,cas;
int a[maxl],ehead[maxl],num[maxl];
struct ed{int to,nxt;double l;} e[maxl*maxl*2];
bool in[maxl],vis[maxl];
double ans,maxlen;
double dis[maxl];
void prework()
{
int u,v;
scanf("%d%d",&n,&m);
memset(ehead,0,sizeof(ehead));
maxlen=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d%lf",&u,&e[i].to,&e[i].l);
e[i].nxt=ehead[u];ehead[u]=i;
if(e[i].l>maxlen);
maxlen=e[i].l;
}
}
bool spfa(int s,double x)
{
int u,v,head=0,tail=1;
queue <int> q;
for(int i=1;i<=n;i++)
dis[i]=inf,num[i]=0;
a[1]=s;num[s]=1;dis[s]=0;in[s]=true;vis[s]=true;
while(head!=tail)
{
++head;head=head%maxl;
u=a[head];in[u]=false;
if(num[u]>n)
return true;
for(int i=ehead[u];i>0;i=e[i].nxt)
{
v=e[i].to;
if(dis[v]>dis[u]+e[i].l-x)
{
dis[v]=dis[u]+e[i].l-x;
if(!in[v])
{
in[v]=true;num[v]++;
tail++;tail=tail%maxl;
a[tail]=v;vis[v]=true;
}
}
}
}
return false;
}
bool jug(double x)
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++)
if(!vis[i])
if(spfa(i,x))
return true;
return false;
}
void mainwork()
{
double l=0,r=10000010,mid;
if(!jug(r))
{
ans=inf;
return;
}
while(l+eps<r)
{
mid=(l+r)/2.0;
if(jug(mid))
r=mid;
else
l=mid;
}
ans=l;
}
void print()
{
printf("Case #%d: ",cas);
if(ans>10000000)
printf("No cycle found.\n");
else
printf("%.2f\n",ans);
}
int main()
{
int t;scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}