【HDU4360】 最短路变形

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4360

 

题目大意:屌丝DD从地点1到地点n去找他的女神QQ,总共n个点,两个点之间可能有多条路,每条路上记录一个距离w和一个状态c,DD只能按女神要求走,即 ‘L’->’O’->’V’->’E’->’L’->’O’->’V’->’E’->.... etc,走到终点时LOVE必须是完整的,而且最少有一个LOVE。

 

解题思路:开始用优先队列+bfs做,TLE,这样做不能对点标记,只能对边标记,所以一个点的同一状态可能很多次入队列,无奈的TLE。这题其实仔细想想就是简单的spfa嘛,只不过多存了几个状态,因为只能沿着L->O->V->E走,每个点只有四个状态(‘L’,‘O’,'V',‘E’)而且一定是满足要求的。这题简单扼,但为嘛我还WA了两天?!!!!注意1这个自循环点,超级大bug,蛋疼不已。

 

  1 #include <iostream>

  2 #include <cstdio>

  3 #include <cstring>

  4 #include <algorithm>

  5 using namespace std;

  6 

  7 typedef long long lld;

  8 const int mn=3333;

  9 const int mm=33333;

 10 const lld oo=1e15;

 11 int  reach[mm], next[mm], flow[mm], ch[mm];

 12 lld  head[mn], que[mn], dis[mn][4], cnt[mn][4], inque[mn];

 13 int n, edge;

 14 

 15 void addedge(int u, int v, int c1, int c2,  char c)

 16 {

 17     ch[edge]=c, reach[edge]=v, flow[edge]=c1, next[edge]=head[u], head[u]=edge++;

 18     ch[edge]=c, reach[edge]=u, flow[edge]=c2, next[edge]=head[v], head[v]=edge++;

 19 }

 20 

 21 int find(char c)

 22 {

 23    if(c=='L') return 0;

 24    else if(c=='O') return 1;

 25    else if(c=='V') return 2;

 26    else return 3;

 27 }

 28 

 29 bool spfa()

 30 {

 31     int l=0, h=0;

 32     memset(inque,0,sizeof(inque));

 33     for(int i=1; i<=n; i++)

 34         for(int j=0; j<4; j++) dis[i][j]=oo, cnt[i][j]=0;

 35     inque[1]=1;

 36     dis[1][0]=0;

 37     que[l++]=1;

 38     while(l!=h)

 39     {

 40         int u=que[h++];

 41         if(h==mn) h=0;

 42         inque[u]=0;

 43         for(int i=head[u]; i>=0; i=next[i])

 44         {

 45             int s=find(ch[i]), v=reach[i], val=flow[i];

 46             if(dis[v][(s+1)%4]>=dis[u][s]+val)

 47             {

 48                 if(dis[v][(s+1)%4]==dis[u][s]+val)

 49                 {

 50                     if(cnt[u][s]+1>cnt[v][(s+1)%4]) cnt[v][(s+1)%4]=cnt[u][s]+1;

 51                     else continue;

 52                 }

 53                 else

 54                 {

 55                     dis[v][(s+1)%4]=dis[u][s]+val;

 56                     cnt[v][(s+1)%4]=cnt[u][s]+1;

 57                 }

 58                 if(!inque[v])

 59                 {

 60                     inque[v]=1;

 61                     que[l++]=v;

 62                     if(l==mn) l=0;

 63                 }

 64             }

 65         }

 66     }

 67     if(dis[n][0]==oo||!cnt[n][0]) return false;

 68     else return true;

 69 }

 70 

 71 int main()

 72 {

 73     int m, T, tcase=0;

 74     cin >> T;

 75     while(T--)

 76     {

 77         cin >> n >> m;

 78         edge=0;

 79         memset(head,-1,sizeof(head));

 80         int mp[4]={0,0,0,0}, ct=0;

 81         while(m--)

 82         {

 83             int u, v, val, se;

 84             char sh[3];

 85             scanf("%d%d%d%s",&u,&v,&val,sh);

 86             addedge(u,v,val,val,sh[0]);

 87             if(n==1&&u==1&&v==1)

 88             {

 89                 se=find(sh[0]);

 90                 if(!mp[se]) ct++, mp[se]=val;

 91                 else mp[se]=min(mp[se],val);

 92             }

 93         }

 94         if(ct==4)

 95         {

 96            lld sum=mp[0]+mp[1]+mp[2]+mp[3];

 97            printf("Case %d: Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n",++tcase,sum,ct/4);

 98            continue;

 99         }

100         bool ok=spfa();

101         if(!ok) printf("Case %d: Binbin you disappoint Sangsang again, damn it!\n",++tcase);

102         else printf("Case %d: Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n",++tcase,dis[n][0],cnt[n][0]/4);

103     }

104     return 0;

105 }

106 /*

107 100

108 1 4

109 1 1 1 L

110 1 1 1 O

111 1 1 1 V

112 1 1 1 E

113 */
View Code

 

 

 

你可能感兴趣的:(360)