题意:每条边除了有边权以外,还有一个字母标记。标记可以是“LOVE”里面任意字符。
思路:这题是最短路的变形,用spfa需要记录一下到达这点时,有“LOVE”这四个字母结尾的四种状态,记录每一个状态的最短路,当最短路相等时选love最多的。这题找下一个点时需要两个字母是连在一块的
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <cstdio>
#include <map>
#define MAXN 10050
#define MAXM 83520
#define inf 9223372036854775807
using namespace std;
int head[MAXN];
int cnt=0;
int n,m;
int get(char c)
{
if(c=='L')return 1;
if(c=='O')return 2;
if(c=='V')return 3;
if(c=='E')return 4;
}
struct Node
{
int v,next;
int w;
int ch;
}edge[MAXN*20];
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,char ch)
{
edge[cnt].v=v;
edge[cnt].ch=get(ch);
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
struct NN
{
int num;
int falg;
};
__int64 dis[MAXN][6];
int ans[MAXN][6];
void spfa()
{
int vis[MAXN][6];
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
for(int j=1;j<=4;j++)
{
dis[i][j]=inf;
ans[i][j]=0;
}
memset(ans,0,sizeof(ans));
queue<NN>myqueue;
while(!myqueue.empty())myqueue.pop();
NN f;
f.falg=4;
f.num=1;
myqueue.push(f);
vis[1][4]=1;
dis[1][4]=0;
NN top;
while(!myqueue.empty())
{
top=myqueue.front();
myqueue.pop();
int u=top.num;
int ff=top.falg;
vis[u][ff]=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int hh=edge[i].ch;
int v=edge[i].v;
int f=ff+1;
if(f>4)f=f%4;
if(dis[u][ff]+edge[i].w<dis[v][hh]&&f==hh)//距离较短则距离和“LOVE”个数都要更新
{
dis[v][hh]=dis[u][ff]+edge[i].w;
ans[v][hh]=ans[u][ff];
if(hh==4)
ans[v][4]++;
NN ne;
ne.num=v;
ne.falg=hh;
if(!vis[v][hh])
{
vis[v][hh]=1;
myqueue.push(ne);
}
}
else if(dis[v][hh]<inf&&dis[u][ff]+edge[i].w==dis[v][hh]&&f==hh)//距离相等则更新"LOVE"个数
{
if(ans[v][hh]<=ans[u][ff])
{
ans[v][hh]=ans[u][ff];
if(hh==4)
ans[v][hh]++;
if(!vis[v][hh])
{
vis[v][hh]=1;
NN ne;
ne.num=v;
ne.falg=hh;
myqueue.push(ne);
}
}
}
}
if(n==1&&ans[n][4]==0&&dis[n][4]==0)//只有一个点
dis[n][4]=inf;
}
}
int main()
{
int u,v;
long long w;
int cas;
char ch[10];
int T=0;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=m;i++)
{
scanf("%d %d %d %s",&u,&v,&w,ch);
addedge(u,v,w,ch[0]);//双向边
addedge(v,u,w,ch[0]);
}
spfa();
T++;
if(ans[n][4] == 0 || dis[n][4] >= inf)
printf("Case %d: Binbin you disappoint Sangsang again, damn it!\n", T);
else
printf("Case %d: Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n", T, dis[n][4], ans[n][4]);
}
return 0;
}