1486: [HNOI2009]最小圈
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2224 Solved: 1046
[ Submit][ Status][ Discuss]
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
题解:01分数规划+深搜版spfa
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define N 20003
#define eps 1e-9
#define inf 1e8
using namespace std;
int n,m,can[N],tot;
int point[N],next[N],v[N];
double len[N],dis[N],mid;
bool pd;
void add(int x,int y,double z)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; len[tot]=z;
}
void spfa(int x)
{
can[x]=1;
for (int i=point[x];i;i=next[i])
if (dis[v[i]]>dis[x]+len[i]-mid) {
dis[v[i]]=dis[x]+len[i]-mid;
if (can[v[i]]==1) {
pd=true;
return;
}
spfa(v[i]);
if (pd) return;
}
can[x]=0;
}
bool check(double x)
{
memset(can,0,sizeof(can));
memset(dis,0,sizeof(dis));
for (int i=1;i<=n;i++) {
pd=false;
spfa(i);
if (pd) return true;
}
return false;
}
int main()
{
freopen("a.in","r",stdin);
scanf("%d%d",&n,&m);
double l=0,r=0;
for (int i=1;i<=m;i++) {
int x,y; double z;
scanf("%d%d%lf",&x,&y,&z);
add(x,y,z);
}
double ans=inf; l=-inf; r=inf;
while (r-l>=eps) {
mid=(l+r)/2;
if (check(mid)) ans=min(ans,mid),r=mid-eps;
else l=mid+eps;
}
printf("%.8lf\n",ans);
}