题意:有一个网络,每条边分别被标记上‘L’、‘O’、‘V’、‘E’四个字母,从起点到终点,只能按照LOVELOVE.....的走。求在保证LOVE的情况下的最短路。
利用spfa,将每条路标记上四个状态,求最短路即可。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int mm=5555;
const int mn=99999;
#define INF 1000000000000LL
int head[mm],vis[mm][4],num[mm][4];
int n,m,e;
long long d[mm][4];
struct Edge
{
int v,next;
long long w;
int id;
};
Edge edge[mn];
struct P
{
int u,id;
P() {}
P(int a,int b) {u=a;id=b;}
};
P q[mn*10];
void init()
{
e=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,long long w,char c)
{
edge[e].v=v;edge[e].w=w;edge[e].next=head[u];
if(c == 'L') edge[e].id = 0;
if(c == 'O') edge[e].id = 1;
if(c == 'V') edge[e].id = 2;
if(c == 'E') edge[e].id = 3;
head[u]=e++;
}
void spfa(int src)
{
int h=0,t=0;
for(int i=0;i<=n;i++)
for(int j=0;j<4;j++)
d[i][j]=INF, vis[i][j]=0, num[i][j]=0;
vis[src][3]=1;
d[src][3]=0;
P tmp=P(src,3);
q[t++]=tmp;
while(h<t)
{
tmp=q[h++];
int u=tmp.u;
int id=tmp.id;
vis[u][id]=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
int x=edge[i].id;
long long w=edge[i].w;
if((d[u][id]+w<d[v][x]||d[v][x]==0)&&(id+1)%4==x)
{
d[v][x]=d[u][id]+w;
num[v][x]=num[u][id];
if(x==3) num[v][x]++;
if(!vis[v][x])
{
q[t++]=P(v,x);vis[v][x]=1;
}
}
else if((d[u][id]+w==d[v][x]||d[v][x]==0)&&(id+1)%4==x&&num[v][x]<=num[u][id])
{
num[v][x]=num[u][id];
if(x==3) num[v][x]++;
if(!vis[v][x])
{
q[t++]=P(v,x);
vis[v][x]=1;
}
}
}
}
}
int main()
{
int t,cas=0;
int u,v,w;
char s[5];
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&n,&m);
while(m--)
{
scanf("%d%d%d%s",&u,&v,&w,s);
addedge(u,v,w,s[0]);
addedge(v,u,w,s[0]);
}
spfa(1);
//cout<<num[n][3]<<" "<<d[n][3]<<endl;
if(num[n][3]==0 || d[n][3]==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, d[n][3], num[n][3]);
}
return 0;
}