*

然后这个题是01分数规划,然而我并miu看出来,然后看了两分钟,happy的写了个floyd,然后成功挂掉。

这个题然后其实是一个

设路程数组为dis,时间为tim。
设一个数组x,x[i] = 1表示第i条边在所选的路线中,x[i] = 0表示第i条边不在路线中,(所以,dis[i],tim[i],为定值,x[i]不是定值,x[i]会随着你跑spfa而变)

然后我们把式子列出来就是:

R=(i=1ndis[i]x[i]∑i=1ndis[i]∗x[i])/(i=1ntim[i]x[i]∑i=1ntim[i]∗x[i])

。。。。他不支持markdown。。。。。。

  当f(L)==0时,(看上面)L就是我们要求的R,就是最优解。

  当f(L)>0时:

 

  那么什么时候f(L) > 0呢?
  有两种情况:
  1、dist[n] > 0:
  上面已经说了,dist[n]就相当于L,所以dist[n] > 0时,L就大于0咯。
  2、存在正环:
  因为本题是跑最长路,如果你找到一个正环,在里面一直绕,当前的权值肯定是非常大的,dist[n]一定大于0。

  然后L就二分答案求一下,注意精度。。。然后就没有然后了。。。。

  

#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef double db;
const int maxn=20000;
const db inf=0x7ffffff;
struct Edge {
	int f;
	int to;
	db d;
	db tim;
	int next;
} edge[maxn];
int head[maxn],time[maxn];
db dist[maxn];
bool vis[maxn];
int n;
db dis[150][150],tim[150][150];
int tot;
void add(int f,int t,db d,db tt) {
	edge[++tot].to = t;
	edge[tot].d = d;
	edge[tot].tim = tt;
	edge[tot].next = head[f];
	head[f] = tot;
}
deque<int>q;
void clr() {
	tot = 0;
	while(!q.empty())
		q.pop_front();
	for(int i = 1; i <= n; i++)
		dist[i] = -inf;
	memset(vis,0,sizeof(vis));
	memset(time,0,sizeof(time));
//  printf("%lf
",dist[1]);
}
bool spfa(db mid) {
	clr();
	q.push_front(1);
	dist[1] = 0.0;
	while(!q.empty()) {
		int x = q.front();
		q.pop_front();
		vis[x] = 0;
		for(int i = head[x]; i; i = edge[i].next) {
			Edge e = edge[i];
			if(dist[e.to] < dist[x] + (e.d - mid * e.tim)) {
				dist[e.to] = dist[x] + (e.d - mid * e.tim);
				if(!vis[e.to]) {
					vis[e.to] = true;
					time[e.to]++;
					if(time[e.to] > n) {
						return true;
					}
					if(!q.empty() && dist[e.to] > dist[q.front()])
						q.push_front(e.to);
					else
						q.push_back(e.to);
				}
			}
		}
	}
	if(dist[n] > 0)
		return true;
	return false;
}
db div() {
	db l = 0,r = 100000000;
	db ans = 0;
	int k = 0;
	while(k <= 100) {
		double mid = ((l + r) / (double)(2));
		if(!spfa(mid))
			r = mid;
		else
			l = mid,ans = max(ans,mid);
		k ++;
		//  printf("l:%.1lf r:%.1lf
",l,r);
	}
	return ans;
}
int main() {
	scanf("%d",&n);
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
			scanf("%lf",&dis[i][j]);
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
			scanf("%lf",&tim[i][j]);
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			if(i != j) {
				add(i,j,dis[i][j],tim[i][j]);
			}
		}
	}
	printf("%.3f",div());
	return 0;
}

  

 

原文地址:https://www.cnblogs.com/excellent-zzy/p/11288552.html