鸽了好久的01分数规划…
思路分析:
环中点数==边数,所以我们可以直接转化成边权搞。
思路跟之前的都一样,二分答案,用SPFA判断图中是否有正权环即可。
题目链接:
玄学问题:
我用FIFO队列,第一个元素不入队为啥啊,跪求路过大牛教导。
AC代码:
#include <cstdio>
#include <iostream>
#include <queue>
#define il inline
const int maxm=1e7+1;
const double eps=1e-6;
int dl[maxm];
int head[maxm],net[maxm],to[maxm],cur[maxm];
double cost[maxm],f[maxm],dis[maxm];
bool vis[maxm];
int cnt=0;
int n,m;
il void add_edge(int u,int v,double c)
{
to[++cnt]=v,cost[cnt]=c;
net[cnt]=head[u],head[u]=cnt;
}
il bool SPFA(double mid)
{
int fis=0,tail=0;
for(int i=1;i<=n;i++)
{
vis[i]=1,dl[++tail]=i;
dis[i]=0,cur[i]=1;
}
while(fis<=tail)
{
int x=dl[++fis];
vis[x]=0;
for(int i=head[x];i;i=net[i])
{
double w=f[x]-(cost[i]*mid);
if(dis[to[i]]<dis[x]+w)
{
dis[to[i]]=dis[x]+w;
if(vis[to[i]]) continue;
vis[to[i]]=1,dl[++tail]=to[i];
cur[to[i]]++;
if(cur[to[i]]>n) return 1;
}
}
}
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
double l=0,r=0;
for(int i=1;i<=n;i++)
{
scanf("%lf",&f[i]);
r+=f[i];
}
for(int i=1;i<=m;i++)
{
int u,v;
double c;
scanf("%d%d%lf",&u,&v,&c);
add_edge(u,v,c);
}
while(r-l>eps)
{
double mid=(l+r)/2.0;
int d=SPFA(mid);
//printf("%.2lf %d\n",mid,d);
if(d) l=mid;
else r=mid;
}
return printf("%.2lf\n",l)*0;
}