HDU - 4725 最短路
题意:
n层图,每个点放在一层,然后给了n个点,相邻的两层距离是固定的c,有额外m条边,然后求1到n的最短路径,如果没有则输出-1
题解:
这道题原来我想着还用1到n表示点,层用n+1到2*n表示,但是这样是不行的,因为这样建图的话就相当于同层之间的距离为0.但是事实证明不是这样的
我按照上面建图就Wa了
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 using namespace std; 8 const int INF=0x3f3f3f3f; 9 const int maxn=3e5+5; 10 #define MAX 0xffffff 11 struct shudui1 12 { 13 int start,value; 14 bool operator < (const shudui1 q)const 15 { 16 return value>q.value; 17 } 18 } str1; 19 struct shudui2 20 { 21 int start,value; 22 } str2; 23 int v[maxn]; 24 priority_queue<shudui1>r; 25 vector <shudui2>w[maxn]; 26 void JK(int s) 27 { 28 memset(v,INF,sizeof(v)); 29 v[s]=0; 30 str1.start=s; 31 str1.value=0; 32 r.push(str1); 33 while(!r.empty()) 34 { 35 int x,y; 36 str1=r.top(); 37 r.pop(); 38 x=str1.start; 39 y=str1.value; 40 if(v[x]<y) continue; 41 int len=w[x].size(); 42 for(int i=0; i<len; ++i) 43 { 44 str2=w[x][i]; 45 if((v[x]+str2.value<v[str2.start])) 46 { 47 v[str2.start]=v[x]+str2.value; 48 str1.start=str2.start; 49 str1.value=v[str2.start]; 50 r.push(str1); 51 } 52 } 53 } 54 } 55 int main() 56 { 57 int t,p=0; 58 scanf("%d",&t); 59 while(t--) 60 { 61 int n,m,k; 62 scanf("%d%d%d",&n,&m,&k); 63 for(int i=1;i<=2*n;++i) 64 w[i].clear(); 65 for(int i=1;i<=n;++i) 66 { 67 int x; 68 scanf("%d",&x); 69 str2.start=n+x; 70 str2.value=0; 71 w[i].push_back(str2); 72 str2.start=i; 73 w[n+x].push_back(str2); 74 } 75 for(int i=2;i<=n;++i) 76 { 77 str2.start=n+i; 78 str2.value=k; 79 w[n+i-1].push_back(str2); 80 str2.start=n+i-1; 81 w[n+i].push_back(str2); 82 } 83 for(int i=1;i<=m;++i) 84 { 85 int x,y,z; 86 scanf("%d%d%d",&x,&y,&z); 87 str2.start=y; 88 str2.value=z; 89 w[x].push_back(str2); 90 str2.start=x; 91 w[y].push_back(str2); 92 } 93 JK(1); 94 if(v[n]!=INF) 95 printf("Case #%d: %d\n",++p,v[n]); 96 else printf("Case #%d: -1\n",++p); 97 } 98 return 0; 99 }
那就只好把每一层分成两个点,一个当作入点,一个当作出点。
第i层,入边到N+2*i-1, 出边从N+2*i 出来。(1<= i <= N)
N + 2*i 到 N + 2*(i+1)-1 加边长度为C. 表示从第i层到第j层。
N + 2*(i+1) 到 N + 2*i - 1 加边长度为C,表示第i+1层到第j层。
建完图直接最短路就行了
AC代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 using namespace std; 8 const int INF=0x3f3f3f3f; 9 const int maxn=3e5+5; 10 #define MAX 0xffffff 11 struct shudui1 12 { 13 int start,value; 14 bool operator < (const shudui1 q)const 15 { 16 return value>q.value; 17 } 18 } str1; 19 struct shudui2 20 { 21 int start,value; 22 } str2; 23 int v[maxn]; 24 priority_queue<shudui1>r; 25 vector <shudui2>w[maxn]; 26 void JK(int s) 27 { 28 memset(v,INF,sizeof(v)); 29 v[s]=0; 30 str1.start=s; 31 str1.value=0; 32 r.push(str1); 33 while(!r.empty()) 34 { 35 int x,y; 36 str1=r.top(); 37 r.pop(); 38 x=str1.start; 39 y=str1.value; 40 if(v[x]<y) continue; 41 int len=w[x].size(); 42 for(int i=0; i<len; ++i) 43 { 44 str2=w[x][i]; 45 if((v[x]+str2.value<v[str2.start])) 46 { 47 v[str2.start]=v[x]+str2.value; 48 str1.start=str2.start; 49 str1.value=v[str2.start]; 50 r.push(str1); 51 } 52 } 53 } 54 } 55 int main() 56 { 57 int t,p=0; 58 scanf("%d",&t); 59 while(t--) 60 { 61 int n,m,k; 62 scanf("%d%d%d",&n,&m,&k); 63 for(int i=1;i<=3*n;++i) 64 w[i].clear(); 65 for(int i=1;i<=n;++i) 66 { 67 int x; 68 scanf("%d",&x); 69 str2.start=n+2*x-1; 70 str2.value=0; 71 w[i].push_back(str2); 72 str2.start=i; 73 w[n+2*x].push_back(str2); 74 } 75 for(int i=1;i<n;++i) 76 { 77 str2.start=n+2*(i+1); 78 str2.value=k; 79 w[n+2*i-1].push_back(str2); 80 81 str2.start=n+2*i; 82 w[n+2*(i+1)-1].push_back(str2); 83 } 84 for(int i=1;i<=m;++i) 85 { 86 int x,y,z; 87 scanf("%d%d%d",&x,&y,&z); 88 str2.start=y; 89 str2.value=z; 90 w[x].push_back(str2); 91 str2.start=x; 92 w[y].push_back(str2); 93 } 94 JK(1); 95 if(v[n]!=INF) 96 printf("Case #%d: %d\n",++p,v[n]); 97 else printf("Case #%d: -1\n",++p); 98 } 99 return 0; 100 }