每条边除了有边权以外,还有一个字母标记。标记可以是“LOVE”里面任意字符。
每个点,要拆成四个点,分别代表到达该点的标记为L,O,V,E的最短路。
第一步就是求最短路,直接Dijkstra就可以了。
trick在于,至少要找到一个LOVE串,在只有一个节点的时候,有几条自环,至少必须走LOVE四条自环。此时,必须另外加一个节点表示开始节点。
还有一个trick就是距离可能超过int。
1 2 1314520 L
1 2 1314520 O
1 2 1314520 V
2 3 1314520 E
3 4 1314520 L
3 4 1314520 O
3 4 1314520 V
4 5 1314520 E
...
这种情况下1313个点,2624条边,每条边长度1314520,并且每条边都必须走,所以,超int了(至少signed不够)。
这道题主要就是trick多,比赛的时候wrong answer了好多次,我基本把所有的trick都经历了一遍
下面是我ac的代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <list>
using namespace std;
typedef long long ll;
const int M = 1500;
const int N = 15000;
ll INF = 1 << 30;
struct node
{
int to;
int w;
int ch;
bool bo;
node *next;
}d[M];
node pool[2 * N];
int n,m,s,t,top;
ll dist[M][4];
int num[M][4];
void INIT();
void Dijkstra();
int change(char ch)
{
if(ch == 'L')return 0;
else if(ch=='O')return 1;
else if(ch == 'V')return 2;
else if(ch == 'E')return 3;
}
int main()
{
int ttt,cas=1;
INF = INF * INF;
scanf("%d",&ttt);
while(ttt--)
{
scanf("%d%d",&n,&m);
INIT();
Dijkstra();
if(dist[n][0] == INF)printf("Case %d: Binbin you disappoint Sangsang again, damn it!\n",cas++);
else
{
printf("Case %d: Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n",cas++,dist[t][0],num[t][0]);
}
}
return 0;
}
void INIT()
{
ll u,v,w;
char str[3];
for(int i = 1;i <= M;i++)
{
d[i].next = NULL;
dist[i][0] = dist[i][1] = dist[i][2] = dist[i][3] = INF;
}
memset(num,0,sizeof(num));
s = 1;
t = n;
top = 0;
for(int i = 0;i < m;i++)
{
scanf("%d%d%d",&u,&v,&w);
scanf("%s",&str);
pool[top].to = v;
pool[top].w = w;
pool[top].ch = change(str[0]);
pool[top].next = d[u].next;
d[u].next = &pool[top++];
pool[top].to = u;
pool[top].w = w;
pool[top].ch = change(str[0]);
pool[top].next = d[v].next;
d[v].next = &pool[top++];
}
return;
}
void Dijkstra()
{
int flag,g,numlove;
node *st;
priority_queue< pair<ll,pair<int,int> > > qu;
while(!qu.empty())qu.pop();
qu.push(make_pair(0,make_pair(s,0)));
while(!qu.empty())
{
flag = qu.top().second.first;
g = qu.top().second.second;
ll di = -qu.top().first;
qu.pop();
numlove = num[flag][g];
st = d[flag].next;
int y = (g +1) % 4;
if(g + 1 == 4) numlove++;
while(st!=NULL)
{
long long x = st->ch;
if(x == g)
{
if(dist[st->to][y] > di + st->w)
{
dist[st->to][y] = di + st->w;
num[st->to][y] = numlove;
qu.push(make_pair(-dist[st->to][y],make_pair(st->to,y)));
}
else if(dist[st->to][y] == di + st->w&&numlove > num[st->to][y])
{
dist[st->to][y] = di + st->w;
num[st->to][y] = max(numlove,num[st->to][y]);
qu.push(make_pair(-dist[st->to][y],make_pair(st->to,y)));
}
}
st = st->next;
}
}
return;
}