爱情之路
【題目描述】
有n(n <= 1314)個城市和m(m <= 13520)條雙向公路,每條公路連接著一個或兩個城市,通過一條公路需要耗費時間,且每條公路均有一個特定標識“L”、“O”、“V”、“E”。
小Y從1號城市出發,需要前往n號城市,他必須按照“L” --> “O” --> “V” --> “E” --> “L” --> “O” --> “V” --> “E” --> ······的順序選擇公路,且其所走的第一條公路為“L”,最后一條公路為“E”,每走完一個完整的“LOVE”就算通過了一次考驗。
現詢問小Y耗費的最少時間是多少,以及在該時間內最多能夠通過多少次考驗。
【輸入描述】第一行輸入兩個整數n、m,表示城市數目和公路數目;
接下來m行,每行輸入三個整數X、Y、T和一個字符,表示城市X、Y之間存在一條公路,通過這條公路需耗費時間T,及其特殊標志。
【輸出描述】輸出兩個整數,分別表示耗費最少的時間,以及在該時間內能夠通過的最多的考驗次數,如果不能到達n號城市,輸出“HOLY?SHIT!”。
【樣例輸入】樣例1:
4?4
1?2?1?L
2?1?1?O
1?3?1?V
3?4?1 E
?
樣例2:
4?4
1?2?1?L
2?3?1?O
3?4?1?V
4?1?1?E
【樣例輸出】
樣例1:
4?1
?
樣例2:
HOLY?SHIT!
源代碼:#include<cstdio> #include<cstring> #include<queue> using namespace std; struct Node {int T,S,T1,T2; }i[27051]; //兩倍。 queue <int> Q; int n,m,Head[1315],Next[13521],dis[1315][4],Road[1315][4]; bool Vis[1315]={0}; void SPFA() //SPFA快忘掉了。 {memset(dis,0x3f,sizeof(dis)); //dis[i][j]表示走到節點i,且后續字母編號應為j的最短路數值。Q.push(1);Vis[1]=true; //是否在隊列之中。dis[1][3]=0;bool Flag(0);while (!Q.empty()){int t=Q.front();Q.pop();Vis[t]=false;for (int a=Head[t];a;a=Next[a]) //遍歷此點的邊。 {int T=i[a].T2;if (dis[t][(i[a].T+3)%4]==0x3f) //字母不符條件。continue;if (dis[t][(i[a].T+3)%4]+i[a].S==dis[T][i[a].T]) //最短路數值相等。 {if (i[a].T==3)Road[T][3]=max(Road[t][2]+1,Road[T][3]); //Road[i][j]表示走到節點i,且此節點字母編號為j的最多考驗數值。elseRoad[T][i[a].T]=max(Road[T][i[a].T],Road[t][(i[a].T+3)%4]);}if (dis[t][(i[a].T+3)%4]+i[a].S<dis[T][i[a].T]) //更新最短路。 {if (i[a].T==3)Road[T][3]=Road[t][2]+1;elseRoad[T][i[a].T]=Road[t][(i[a].T+3)%4];dis[T][i[a].T]=dis[t][(i[a].T+3)%4]+i[a].S;if (!Vis[T]){Q.push(T); //入隊。Vis[T]=true; /* 判斷負環,但在本題中沒有必要。Sum[T]++;if (Sum[T]>n) //入隊的次數大于節點總數,肯定就是陷入死循環了。return; */}}}if (n==1&&!Flag) //自環,因為前面已經把dis[1][3]賦值為0,暴力判斷并修改一次即可。 {Flag=true;dis[1][3]=0x3f;}} } void Init() //類似于邊表,只不過邊表是按Num++序,但此數據結構直接跳到了邊數之外。 {for (int a=1;a<=m;a++){char t;scanf("%d%d%d",&i[a].T1,&i[a].T2,&i[a].S);scanf(" %c",&t); //新字符讀入方式get√。if (t=='L')i[a].T=0;if (t=='O')i[a].T=1;if (t=='V')i[a].T=2;if (t=='E')i[a].T=3;Next[a]=Head[i[a].T1]; //Next[]存儲的是此節點的上一條邊的編號。Head[i[a].T1]=a; //Head[]存儲的是該條邊的編號,為下一條邊的處理做準備。i[a+m].T1=i[a].T2; //無向邊就是兩條有向邊。i[a+m].T2=i[a].T1;i[a+m].S=i[a].S;i[a+m].T=i[a].T;Next[a+m]=Head[i[a+m].T1]; //同理于上。Head[i[a+m].T1]=a+m;} } int main() //這道題目敘述有意思啊。 {scanf("%d%d",&n,&m);Init();SPFA();if (dis[n][3]==0x3f) //無法得出答案。printf("HOLY SHIT!");elseprintf("%d %d",dis[n][3],Road[n][3]);return 0; }轉載于:https://www.cnblogs.com/Ackermann/p/5990040.html
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結