hdu:4360(spfa)求各种状态的最短路

53 篇文章 0 订阅

题意:每条边除了有边权以外,还有一个字母标记。标记可以是“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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值