http://poj.org/problem?id=3621
分数规划+二分 最优比率环
不是很难 本题中没有说明从哪个点开始 不过好像默认为1就可以过 poj数据又水了
里面的用spfa判定部分还是不太懂
代码及其注释:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<string.h>
using namespace std;
const double eps=1e-5;
const int N=1001;
const int M=5005;
int head[N];//邻接表头
struct node
{
int j,k;
int next;
}side[M];边
int value[N];//点的价值
bool in[N];//是否在队列中
int innum[N];//如队列次数
double dist[N];//记录
queue<int>str;
void build(int x,int t)//建树
{
side[t].next=head[x];
head[x]=t;
}
bool spfa(double L,int n)//看是否有正环 如果有返回true
{
while(!str.empty())
str.pop();
for(int i=1;i<=n;++i)
{
dist[i]=0.0;
str.push(i);
}
memset(in,true,sizeof(in));
memset(innum,0,sizeof(innum));
while(!str.empty())
{
int x=str.front();
str.pop();
in[x]=false;
int t=head[x];
while(t!=-1)
{//cout<<t<<endl;
int j=side[t].j;
if(dist[j]<dist[x]+value[j]-L*side[t].k)
{
dist[j]=dist[x]+value[j]-L*side[t].k;
if(!in[j])
{
str.push(j);
in[j]=true;
++innum[j];
if(innum[j]>=n)//有环
return true;
}
}
t=side[t].next;
}
}
return false;
}
int main()
{
// freopen("data.txt","r",stdin);
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
memset(head,-1,sizeof(head));
for(int i=1;i<=n;++i)
scanf("%d",&value[i]);
for(int i=1;i<=m;++i)
{
int x;
scanf("%d %d %d",&x,&side[i].j,&side[i].k);
build(x,i);
}
double l=1.0,r=200.0;
while(r-l>eps)//用二分 不断向答案逼近
{
double mid=(l+r)/2.0;
if(spfa(mid,n))
l=mid;
else
r=mid;
}
printf("%.2f\n",l);
}
return 0;
}
浙公网安备 33010602011771号