HDU 2962 Trucking

传送门

二分枚举最短路。和HDU 1839几乎完全一样。

都是先最小找最大(边权cap),然后再求最短路(边权len),无向图。这道题说的什么高度和运量是一个意思。限制高度就是限制运量,最大化运量就是最大化高度。

不同就是这道题不限制最短路上限,而是对最大运量加了一个上限L。这道题的二分数组是[L...0],直接存的就是最大值到最小值的连续区间。与另一种做法:存每条边的容量再从大到小排序再去除大于L的值是等价的。

另外,这道题需要输出最短路的值,所以二分运行到最后l=r之后还要再来一次spfa


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
#include <queue>
using namespace std;

const int INF = 1e9;
const int MAXN = 1001;
int N, M, S, T, L;                 // L:全局上限

struct Edge
{
	int n, cap, len;
};
vector<Edge> ve;
vector<int> v[MAXN];

int limit;
int d[MAXN];
bool vis[MAXN];

void init()
{
	ve.clear();
	for (int i = 1; i <= N; i++)
		v[i].clear();
}

void spfa(int s)
{
	queue<int> q;
	memset(vis, 0, sizeof vis);
	fill(d + 1, d + N + 1, INF);
	
	q.push(s);
	vis[s] = true;
	d[s] = 0;

	for (; !q.empty();)
	{
		int t = q.front();
		q.pop();
		vis[t] = false;
		for (int i = 0; i < v[t].size(); i++)
		{
			int n = ve[v[t][i]].n;
			int cap = ve[v[t][i]].cap;
			int len = ve[v[t][i]].len;
			if (cap >= limit)                    // 
			{
				if (d[t] + len < d[n])
				{
					d[n] = d[t] + len;
					if (!vis[n])
					{
						q.push(n);
						vis[n] = true;
					}
				}
			}
		}
	}
}

bool cmp(const int& a, const int& b)
{
	return a > b;
}

int main()
{
	int a, b, c, dd;
	for (int cnt = 1; ~scanf("%d%d", &N, &M); cnt++)
	{
		if (!N && !M) break;
		init();
		for (int i = 0; i < M; i++)
		{
			scanf("%d%d%d%d", &a, &b, &c, &dd);
			if (c == -1) c = INF;
			ve.push_back(Edge{ b,c,dd });
			ve.push_back(Edge{ a,c,dd });
			v[a].push_back(i << 1);
			v[b].push_back(i << 1 | 1);
		}
		scanf("%d%d%d", &S, &T, &L);

		vector<int> vc;
		for (int i = L; i >= 0; i--)
			vc.push_back(i);
		int l = 0, r = L, mid;
		for (; l <= r;)                             //
		{
			mid = (l + r) >> 1;
			limit = vc[mid];
			spfa(S);
			if (l == r) break;                      //
			if (d[T] != INF) r = mid;
			else l = mid + 1;
		}

		//limit = vc[l];                            // 果然,能找对位置,但d[T]的最后正确输出不能保证,需要再来一次
		//spfa(S);                                  // 不加这两句就WA

		if (cnt > 1) printf("\n");                  // PE
		printf("Case %d:\n", cnt);
		if (d[T] == INF) printf("cannot reach destination\n");
		else
		{
			printf("maximum height = %d\n", vc[l]);
			printf("length of shortest route = %d\n", d[T]);
		}
	}

	return 0;
}
posted @ 2019-04-02 21:00  CrossingOver  阅读(123)  评论(0编辑  收藏  举报