1. 程式人生 > 其它 >做題記錄 Luogu P2868

做題記錄 Luogu P2868

Luogu P2868 [USACO07DEC]Sightseeing Cows G

分數規劃。

#include<bits/stdc++.h>
using namespace std;
#define N 100005
struct edge
{
	int from, to, w, Next;
};
edge e[N];
const double eps = 1e-6;
int first[N], n, m, tot;
double a[N], dis[N];
int vis[N], mark[N];
void add(int x, int y, int z)
{
	e[++tot].Next = first[x];
	first[x] = tot;
	e[tot].from = x;
	e[tot].to = y;
	e[tot].w = z;
}
int spfa(int x, double mid)
{
	vis[x] = 1;
	mark[x] = 1;
	for(int i = first[x]; i; i = e[i].Next)
	{
		int v = e[i].to;
		double w = mid * e[i].w - a[v];
		if(dis[x] + w < dis[v])
		{
			dis[v] = dis[x] + w;
			if(mark[v])
			{
				return 1;
			}
			if(spfa(v, mid))
			{
				return 1;
			}
		}
	}
	mark[x] = 0;
	return 0;
}
int check(double x)
{
	memset(vis, 0, sizeof(vis));
	memset(mark, 0, sizeof(mark));
	for(int i = 1; i <= n; i++)
	{
		dis[i] = 1e9;
	}
	for(int i = 1; i <= n; i++)
	{
		if(!vis[i])
		{
			if(spfa(i, x))
			{
				return 1;
			}
		}
	}
	return 0;
}
int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i++)
	{
		scanf("%lf", &a[i]);
	}
	int u, v, w;
	for(int i = 1; i <= m; i++)
	{
		scanf("%d%d%d", &u, &v, &w);
		add(u, v, w);
	}
	double l = 0, r = 1e5, mid;
	while(r - l > eps)
	{
		mid = (l + r) / 2;
		if(check(mid))
		{
			l = mid;
		}
		else
		{
			r = mid;
		}
	}
	printf("%0.2lf", l);
	return 0;
}