题目大意:
n(1<=N<=1,314)个点,m(0<=M<=13,520)条边,每个边除了有长度之外,还有一个字母来标记,分别是L,O,V,E中的一个,要求求出从1到n的一条最短路,还要保证走的路径是L->0->V->E->L->……且最后得到的路径必须是完整的LOVE的相加,在最短路长度相同的情况下,要求LOVE尽可能多。
题解:
将一个点,拆成4个点,同时开一个数组let[i]表示到i为止的最短路经过的最大边数,然后使用spfa即可,此时spfa中的三角形不等式要有所变化,见程序。
此题的坑是:当n等于1时,spfa不能求出正确的解,需要特判,且还要注意重边。
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
const long long inf=11111111111111111LL;
long long d[8000],let[8000];
int to[80000],cap[80000],next[80000],edge[80000];
int n,m,em,sec;
bool v[8000];
queue<int> q;
void addedge(int x,int y,int d)
{
em++;
to[em]=y;
cap[em]=d;
next[em]=edge[x];
edge[x]=em;
}
void spfa(int s,int n)
{
for(int i=0;i<=n;i++)
{
d[i]=inf;
v[i]=false;
}
d[s]=0;v[s]=true;q.push(s);
while(!q.empty())
{
int x=q.front();q.pop();
int p=edge[x];
while(p!=-1)
{
if(d[x]<inf && (d[x]+cap[p]<d[to[p]] || (d[x]+cap[p]==d[to[p]] && let[x]+1>let[to[p]])))//最短路相同时,比较let
{
d[to[p]]=d[x]+cap[p];
let[to[p]]=let[x]+1;
if(!v[to[p]])
{
v[to[p]]=true;
q.push(to[p]);
}
}
p=next[p];
}
v[x]=false;
}
}
int main()
{
scanf("%d",&sec);
for(int z=1;z<=sec;z++)
{
scanf("%d%d",&n,&m);
em=0;
for(int i=0;i<=m*4+1;i++)
{
edge[i]=-1;
next[i]=-1;
}
int x,y,tx,ty,dis,c;
char tc;
if(n>1)
{
for(int i=1;i<=m;i++)
{
scanf("%d%d%d %c",&tx,&ty,&dis,&tc);
if(tc=='L')c=0;else
if(tc=='O')c=1;else
if(tc=='V')c=2;else
if(tc=='E')c=3;
x=((c+3)%4)*n+tx;y=c*n+ty;
addedge(x,y,dis);
y=((c+3)%4)*n+ty;x=c*n+tx;
addedge(y,x,dis);
}
memset(let,0,sizeof(let));
spfa(3*n+1,4*n);
}
else
{//特判
long long g[5][5];
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
g[i][j]=inf;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d %c",&tx,&ty,&dis,&tc);
if(tc=='L')c=0;else
if(tc=='O')c=1;else
if(tc=='V')c=2;else
if(tc=='E')c=3;
x=((c+3)%4)*n+tx;y=c*n+ty;
if(dis<g[x][y])g[x][y]=dis;//去重边
y=((c+3)%4)*n+ty;x=c*n+tx;
if(dis<g[y][x])g[y][x]=dis;
}
for(int k=1;k<=4;k++)
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
if(g[i][k]+g[k][j]<g[i][j])g[i][j]=g[i][k]+g[k][j];
d[4]=g[4][4];
let[4]=4;
}
printf("Case %d: ",z);
if(d[4*n]<inf)
{
printf("Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %I64d LOVE strings at last.\n",d[4*n],let[4*n]/4);
}
else
{
printf("Binbin you disappoint Sangsang again, damn it!\n");
}
}
return 0;
}