Tima goes to Xentopia(条件最短路)
Tima goes to Xentopia
思路
首先这题应该用Dijkstra应该是无疑的,但是我们又应该如何表示不同的状态呢,我们定义了\(dis[target][red_num][blue_num]\) 来表示当前道路的状态,然后和一维的Dijkstra一样去更新其最小状态。
但是这里有一个地方需要注意直接\(dis[455][805][805]\),铁定是MLE的,通过仔细读题我们观察到 \(k1 * k2 <= 800\),于是我们可以定义一个\(dis[455][805][100]\) 的状态,如果
\(k1 < k2\) 我们就交换红蓝道路的颜色。于是这题就变成了一个Dijkstra的裸题了,但是我还是被MLE给坑了。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int head[500], to[3000], nex[3000], value[3000], color[3000], cnt = 1;
ll dis[500][810][100];
int visit[500][810][100];
int n, m, s, t, k1, k2;
struct point {
int id, r, b;
ll dis;
point(int _id, int _r, int _b, ll _dis) : id(_id), r(_r), b(_b), dis(_dis) {}
bool operator < (const point & t) const {
return dis > t.dis;
}
};
void Dijkstra() {
memset(dis, 0x3f, sizeof dis);
priority_queue<point> q;
dis[s][0][0] = 0;
q.push(point(s, 0, 0, 0));
while(!q.empty()) {
point temp = q.top();
q.pop();
if(visit[temp.id][temp.r][temp.b]) continue;
visit[temp.id][temp.r][temp.b] = 1;
for(int i = head[temp.id]; i; i = nex[i]) {
point t = point(to[i], temp.r + (color[i] == 1), temp.b + (color[i] == 2), temp.dis + value[i]);
if(t.r > k1 || t.b > k2) continue;//这里一定要判断,否者容易出现不必要的数据,造成数组越界,或者TLE.
if(t.dis < dis[t.id][t.r][t.b]) {
dis[t.id][t.r][t.b] = t.dis;
q.push(t);
}
}
}
printf("%lld\n", dis[t][k1][k2] == INF ? -1 : dis[t][k1][k2]);
}
void add(int x, int y, int w, int c) {
to[cnt] = y;
nex[cnt] = head[x];
value[cnt] = w;
color[cnt] = c;
head[x] = cnt++;
}
int main() {
freopen("in.txt", "r", stdin);
int x, y, w, c;
scanf("%d %d %d %d", &n, &m, &k1, &k2);
bool change = false;
if(k1 < k2) {
swap(k1, k2);
change = true;
}
for(int i = 0; i < m; i++) {
scanf("%d %d %d %d", &x, &y, &w, &c);
if(change) {
if(c == 1) c = 2;
else if(c == 2) c = 1;
}
add(x, y, w, c);
add(y, x, w, c);
}
scanf("%d %d",&s, &t);
Dijkstra();
return 0;
}