题意:
给定n个点m条边的无向图
每次必须沿着LOVE走,到终点时必须是完整的LOVE,且至少走出一个LOVE,
问这样情况下最短路是多少,在一样短情况下最多的LOVE个数是多少。
有自环。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 ll;
const ll Inf = 4611686018427387904LL;
const int N = 1314 + 100;
const int E = 13520 * 2 + 100;
const int M = N * 4 + 100;
struct Edge {
ll len;
int v, f, nex;
Edge() {
}
Edge(int _v, int _f, ll _len, int _nex) {
v = _v;
f = _f;
len = _len;
nex = _nex;
}
};
struct node{
int to, f;
node(int b=0,int d=0):to(b),f(d){}
};
Edge eg[E];
ll dis[N][4], tim[N][4];
bool vis[N][4];
int T, n, g[N], idx; int re(char c) {
if (c == 'L')
return 0;
else if (c == 'O')
return 1;
else if (c == 'V')
return 2;
else
return 3;
}
void addedge(int u, int v, ll len, int f) {
eg[idx] = Edge(v, f, len, g[u]);
g[u] = idx++;
}
void spfa() {
memset(vis, 0, sizeof vis);
for (int i = 0; i < n; ++i)
for (int j = 0; j < 4; ++j) {
dis[i][j] = Inf;
tim[i][j] = 0;
}
queue<node>q;
q.push(node(0,3));
dis[0][3] = 0;
tim[0][3] = 0;
while(!q.empty()){
node u = q.front(); q.pop(); vis[u.to][u.f] = 0;
for(int i = g[u.to]; ~i; i = eg[i].nex){
int y = eg[i].v, f = eg[i].f;
if(f != (u.f+1)%4)continue;
bool yes = false;
if(dis[y][f] > dis[u.to][u.f]+eg[i].len)
{
dis[y][f] = dis[u.to][u.f]+eg[i].len;
tim[y][f] = tim[u.to][u.f];
if(f == 3)
tim[y][f]++;
yes = true;
}
else if(dis[y][f] == dis[u.to][u.f]+eg[i].len) {
ll tmp = tim[u.to][u.f];
if(f == 3)
tmp++;
if(tmp > tim[y][f])
tim[y][f] = tmp, yes = true;
}
else if(tim[y][f]==0) {
ll tmp = tim[u.to][u.f];
if(f == 3)
tmp++;
if(tmp > tim[y][f])
dis[y][f] = dis[u.to][u.f]+eg[i].len, tim[y][f] = tmp, yes = true;
}
if(yes && vis[y][f] == 0)
vis[y][f] = 1, q.push(node(y, f));
}
}
}
void work() {
int m, u, v; ll len;
char s[5];
memset(g, -1, sizeof g);
idx = 0; scanf("%d %d", &n, &m);
while (m -- > 0) {
scanf("%d%d%I64d%s", &u, &v, &len, s);
-- u; -- v;
addedge(u, v, len, re(s[0]));
addedge(v, u, len, re(s[0]));
}
spfa();
ll ansdis = dis[n - 1][3], ansnum = tim[n - 1][3];
printf("Case %d: ", ++T);
if (ansdis == Inf || ansnum == 0) {
puts("Binbin you disappoint Sangsang again, damn it!");
} else {
printf("Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %I64d LOVE strings at last.\n", ansdis, ansnum);
}
}
int main() {
int cas;
T = 0;
scanf("%d", &cas);
while (cas -- > 0)
work();
return 0;
}
/*
99
4 4
1 2 1 L
2 4 1 O
4 1 1 V
1 4 1 E 1 4
1 1 1 L
1 1 1 O
1 1 1 V
1 1 1 E 1 0 */