题目大意:
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; }