【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,蛋疼不已。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 */