您的位置:首页 > 其它

[BZOJ1486][HNOI2009]最小圈(01分数规划图+负环)

2018-03-29 19:22 513 查看

题目:

我是超链接

题解:

相当于是∑wij∑1<L∑wij∑1<L要求更小的啊,然后∑wij−L<0∑wij−L<0

那就是一个图的01分数规划了,如果有负环说明可以更小

注意求负环的时候dis数组要设为0,这样快很多

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N=3005;
const int M=10005;
int tot,nxt[M],point
,v[M],n;
double c[M],dis
;bool vis
,fff;
void addline(int x,int y,double z){++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;}
void spfa(int now,double mid)
{
vis[now]=1;
for (int i=point[now];i;i=nxt[i])
if (dis[v[i]]>dis[now]+c[i]-mid && !fff)
{
dis[v[i]]=dis[now]+c[i]-mid;
if (vis[v[i]]) {fff=1;return;}
spfa(v[i],mid);
}
vis[now]=0;
}
bool check(double mid)
{
fff=0;
memset(dis,0,sizeof(dis));
memset(vis,0,sizeof(vis));
for (int i=1;i<=n;i++)
{
spfa(i,mid);
if (fff) return 1;
}
return 0;
}
int main()
{
int m;scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int x,y;double w;scanf("%d%d%lf",&x,&y,&w);
addline(x,y,w);
}
double l=-10000000,r=10000000;
while (r-l>1e-10)
{
double mid=(l+r)/2;
if (check(mid)) r=mid;
else l=mid;
}
printf("%.8lf",l);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: