Meeting Time(拓扑排序+DP)

链接:https://ac.nowcoder.com/acm/contest/7155/A
来源:牛客网

Bessie and her sister Elsie want to travel from the barn to their favorite field, such that they leave at exactly the same time from the barn, and also arrive at exactly the same time at their favorite field. The farm is a collection of N fields (1 <= N <= 100) numbered 1…N, where field 1 contains the barn and field N is the favorite field. The farm is built on the side of a hill, with field X being higher in elevation than field Y if X < Y. An assortment of M paths connect pairs of fields. However, since each path is rather steep, it can only be followed in a downhill direction. For example, a path connecting field 5 with field 8 could be followed in the 5 -> 8 direction but not the other way, since this would be uphill. Each pair of fields is connected by at most one path, so M <= N(N-1)/2. It might take Bessie and Elsie different amounts of time to follow a path; for example, Bessie might take 10 units of time, and Elsie 20. Moreover, Bessie and Elsie only consume time when traveling on paths between fields – since they are in a hurry, they always travel through a field in essentially zero time, never waiting around anywhere. Please help determine the shortest amount of time Bessie and Elsie must take in order to reach their favorite field at exactly the same moment.

输入描述
A single integer, giving the minimum time required for Bessie and Elsie to travel to their favorite field and arrive at the same moment. If this is impossible, or if there is no way for Bessie or Elsie to reach the favorite field at all, output the word IMPOSSIBLE on a single line.

样例输入
3 3
1 3 1 2
1 2 1 2
2 3 1 2

样例输出
2

样例解释
Bessie is twice as fast as Elsie on each path, but if Bessie takes the path 1->2->3 and Elsie takes the path 1->3 they will arrive at the same time.

思路
d p [ i ] [ j ] dp[i][j] dp[i][j]表示是否可以花费 j j j的时间到达场地 i i i x x x可到达 y y y,转移方程为 d p [ y ] [ j ] dp[y][j] dp[y][j] = d p [ x ] [ j − w ] dp[x][j-w] dp[x][jw],为了保证DP的每一个状态没有后效性,通过拓扑排序确保访问当前节点时,该节点的入度为0,该节点之前的节点不会再对之后的状态转移造成影响。

代码

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int N = 105;
struct Edge {
    
    
	int to, nxt, w1, w2;
} e[N*N];
int head[N];
//dp[i][j]表示能否花费j到达i 
int dp1[N][N*N], dp2[N][N*N];
int in[N], n, m, cnt;
void add_edge(int x, int y, int c, int d) {
    
    
	e[++cnt].to = y;
	e[cnt].w1 = c;
	e[cnt].w2 = d;
	e[cnt].nxt = head[x];
	head[x] = cnt;
}
int main() {
    
    
	//freopen("Meeting Time.txt", "r", stdin);
	scanf("%d%d", &n, &m);
	int a, b, c, d;
	for (int i = 1; i <= m; i++) {
    
    
		scanf("%d%d%d%d", &a, &b, &c, &d);
		add_edge(a, b, c, d);
		in[b]++;
	}
	queue<int> q;
	for (int i = 1; i <= n; i++) {
    
    
		if (in[i] == 0) {
    
    
			q.push(i);
		}
	}
	dp1[1][0] = 1;
	dp2[1][0] = 1;
	while (!q.empty()) {
    
    
		int x = q.front(); q.pop();
		for (int i = head[x]; i ; i = e[i].nxt) {
    
    
			int y = e[i].to;
			in[y]--;
			if (in[y] == 0) q.push(y);
			for (int j = 0; j <= 10000; j++) {
    
    
				if (j >= e[i].w1) dp1[y][j] |= dp1[x][j-e[i].w1];
				if (j >= e[i].w2) dp2[y][j] |= dp2[x][j-e[i].w2];
			}
		}
	}
	//寻找dp1[n][j] == dp2[n][j] 最小的j
	int ans = -1;
	for (int j = 0; j <= 10000; j++) {
    
    
		if (dp1[n][j] == dp2[n][j] && dp1[n][j] == 1) {
    
    
			ans = j;
			break;
		}
	} 
	if (ans != -1) printf("%d\n", ans);
	else printf("IMPOSSIBLE\n");
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_41685509/article/details/108687216