http://poj.org/problem?id=3621
关于01划分问题
https://blog.csdn.net/gengmingrui/article/details/47443705
这个blog讲的已经很清楚了 受益良多
用spfa是为了判负权环,如果一个点被压入栈中超过n次,就代表有一个负权环路。
做题中遇到了一些问题:
1 poj上交题需要选择C++而不是 G++可能在双精度运算上有误差
2 因为spfa我用的模拟栈,结果ss数组开小了,1000个点,居然开222222还小,加了个2就可以了。。。也是无语了。感觉应该开n*n+1的空间。极端情况下就是1000个点每个都被压进去999次。。看来还真是开小了。。。。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
int v,nex;
double cost;
};
node eg[11111];
int hea[5555];
int ss[2222222];
double w[5555];
int js[5555];
bool vis[5555];
double dis[5555];
int e;
int n,m;
void insert(int st,int ed,double cost)
{
eg[e].v=ed;
eg[e].cost=cost;
eg[e].nex=hea[st];
hea[st]=e++;
}
int spfa(double R)
{
memset(js,0,sizeof(js));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
dis[i]=1e15;
int l=0;
int r=1;
ss[l]=1;
vis[1]=1;
dis[1]=0;
js[1]=1;
int t;
while(l<r)
{
t=ss[l];
l++;
vis[t]=0;
for(int i=hea[t];i!=-1;i=eg[i].nex)
{
if(dis[eg[i].v]>dis[t]+R*eg[i].cost-w[t])
{
dis[eg[i].v]=dis[t]+R*eg[i].cost-w[t];
if(vis[eg[i].v]==0)
{
ss[r]=eg[i].v;
r++;
vis[eg[i].v]=1;
js[eg[i].v]++;
if(js[eg[i].v]>n)
return 1;
}
}
}
}
return 0;
}
int main(){
while(cin>>n>>m)
{
e=0;
memset(hea,-1,sizeof(hea));
for(int i=1;i<=n;i++)
cin>>w[i];
int u,v;
double cost;
for(int i=0;i<m;i++)
{
cin>>u>>v>>cost;
insert(u,v,cost);
}
double l=0;
double r=160628;
while(r-l>1e-5)
{
double mid=(r+l)/2;
if(spfa(mid))l=mid;
else r=mid;
}
printf("%.2lf\n",l);
}
return 0;
}