最短路 dijkstra 优先队列
1.裸题 hdu2544
http://acm.hdu.edu.cn/showproblem.php?pid=2544
Way1:
好像不对
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <stdbool.h> 6 #include <set> 7 #include <vector> 8 #include <map> 9 #include <queue> 10 #include <algorithm> 11 #include <iostream> 12 using namespace std; 13 #define maxn 100+5 14 #define inf 1e9 15 16 long dist[maxn],road[maxn][maxn]; 17 bool vis[maxn]; 18 struct cmp 19 { 20 bool operator() (long a,long b) 21 { 22 return dist[a]>dist[b]; 23 } 24 }; 25 priority_queue<long,vector<long>,cmp> f; 26 27 int main() 28 { 29 long n,m,i,j,x,y,z,d; 30 while (1) 31 { 32 scanf("%ld%ld",&n,&m); 33 if (n==0 && m==0) 34 break; 35 for (i=1;i<=n;i++) 36 for (j=1;j<=n;j++) 37 road[i][j]=inf; 38 for (i=1;i<=m;i++) 39 { 40 scanf("%ld%ld%ld",&x,&y,&z); 41 road[x][y]=min(road[x][y],z); 42 road[y][x]=road[x][y]; 43 } 44 for (i=1;i<=n;i++) 45 { 46 vis[i]=false; 47 dist[i]=inf; 48 } 49 dist[1]=0; 50 //pay attention! 51 while (!f.empty()) 52 f.pop(); 53 f.push(1); 54 for (j=1;j<n;j++) //use 'i' wrong! 55 { 56 while (vis[f.top()]) 57 f.pop(); 58 d=f.top(); 59 if (d==n) 60 break; 61 vis[d]=true; 62 f.pop(); 63 64 for (i=1;i<=n;i++) 65 if (!vis[i] && dist[i]>dist[d]+road[i][d]) 66 { 67 dist[i]=dist[d]+road[i][d];; 68 f.push(i); 69 } 70 } 71 printf("%ld\n",dist[n]); 72 } 73 return 0; 74 } 75 /* 76 6 7 77 1 2 10 78 1 2 3 79 1 3 1 80 2 4 3 81 4 5 1 82 5 6 10 83 2 5 1 84 */
Way2:
自行写堆,让堆中的值减小(路径长度减小),在堆中上升。
只要掌握了合理的写法,其实也不是特别不好理解和难写
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <stdbool.h> 6 #include <set> 7 #include <vector> 8 #include <map> 9 #include <queue> 10 #include <algorithm> 11 #include <iostream> 12 using namespace std; 13 #define maxn 10000+5 14 #define inf 1e9 15 16 //pos[i]:编号为i的城市到起点的距离 在 树中的位置 17 long dist[maxn],road[maxn][maxn],tree[maxn],pos[maxn],g=0; 18 bool vis[maxn]; 19 20 //minimum-heap 21 void up(long i) 22 { 23 long j,temp; 24 while (i>1) 25 { 26 j=i>>1; 27 //i>j 28 if (dist[tree[i]]<dist[tree[j]]) 29 { 30 temp=tree[i]; 31 tree[i]=tree[j]; 32 tree[j]=temp; 33 pos[tree[i]]=i; 34 pos[tree[j]]=j; 35 } 36 else 37 break; 38 i=j; 39 } 40 } 41 42 void down(long i) 43 { 44 long j,temp; 45 while ((i<<1)<=g) 46 { 47 j=i<<1; 48 if (dist[tree[j+1]]<dist[tree[j]]) 49 j++; 50 //i<j 51 if (dist[tree[i]]>dist[tree[j]]) 52 { 53 temp=tree[i]; 54 tree[i]=tree[j]; 55 tree[j]=temp; 56 pos[tree[i]]=i; 57 pos[tree[j]]=j; 58 } 59 else 60 break; 61 i=j; 62 } 63 } 64 65 int main() 66 { 67 long n,m,i,j,x,y,z,d; 68 while (1) 69 { 70 scanf("%ld%ld",&n,&m); 71 if (n==0 && m==0) 72 break; 73 for (i=1;i<=n;i++) 74 for (j=1;j<=n;j++) 75 road[i][j]=inf; 76 for (i=1;i<=m;i++) 77 { 78 scanf("%ld%ld%ld",&x,&y,&z); 79 road[x][y]=min(road[x][y],z); 80 road[y][x]=road[x][y]; 81 } 82 for (i=1;i<=n;i++) 83 { 84 vis[i]=false; 85 dist[i]=-1; 86 } 87 dist[1]=0; 88 g=1; 89 tree[1]=1; 90 pos[1]=1; 91 for (j=1;j<n;j++) //use 'i' wrong! 92 { 93 d=tree[1]; 94 if (d==n) 95 break; 96 tree[1]=tree[g]; 97 pos[tree[1]]=1; 98 g--; 99 down(1); 100 101 vis[d]=true; 102 for (i=1;i<=n;i++) 103 if (!vis[i]) 104 { 105 if (dist[i]==-1) 106 { 107 dist[i]=dist[d]+road[i][d]; 108 g++; 109 tree[g]=i; 110 pos[i]=g; 111 up(g); 112 } 113 else if (dist[i]>dist[d]+road[i][d]) 114 { 115 dist[i]=dist[d]+road[i][d]; 116 up(pos[i]); 117 } 118 } 119 } 120 printf("%ld\n",dist[n]); 121 } 122 return 0; 123 } 124 /* 125 6 7 126 1 2 10 127 1 2 3 128 1 3 1 129 2 4 3 130 4 5 1 131 5 6 10 132 2 5 1 133 */
2.多关键字
L3-011. 直捣黄龙
https://www.patest.cn/contests/gplt/L3-011
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <stdbool.h> 6 #include <set> 7 #include <vector> 8 #include <map> 9 #include <queue> 10 #include <stack> 11 #include <algorithm> 12 #include <iostream> 13 using namespace std; 14 #define maxn 200+5 15 #define inf 1e9 16 17 struct node 18 { 19 long kill,dist,free,count; 20 }point[maxn]; 21 22 struct cmp 23 { 24 bool operator() (long a,long b) 25 { 26 return point[a].dist>point[b].dist; 27 } 28 }; 29 priority_queue<long,vector<long>,cmp> f; 30 31 long road[maxn][maxn],kill[maxn],pre[maxn],n; 32 char s[maxn][5]; 33 bool vis[maxn]; 34 35 long find(char ss[]) 36 { 37 long i; 38 for (i=1;i<=n;i++) 39 if (strcmp(s[i],ss)==0) 40 return i; 41 } 42 43 void print(long d) 44 { 45 if (pre[d]!=-1) 46 { 47 print(pre[d]); 48 printf("->%s",s[d]); 49 } 50 else 51 printf("%s",s[d]); 52 } 53 54 int main() 55 { 56 char s1[5],s2[5]; 57 long m,i,j,d,x,y,e; 58 scanf("%ld%ld%s%s",&n,&m,s1,s2); 59 for (i=1;i<=n;i++) 60 { 61 point[i].dist=inf; 62 vis[i]=false; 63 } 64 for (i=1;i<=n;i++) 65 for (j=1;j<=n;j++) 66 road[i][j]=inf+1; 67 point[n].kill=0; 68 strcpy(s[n],s1); 69 pre[n]=-1; 70 point[n].dist=0; 71 point[n].free=0; 72 point[n].count=1; 73 f.push(n); 74 for (i=1;i<n;i++) 75 { 76 scanf("%s%ld",s[i],&kill[i]); 77 if (strcmp(s2,s[i])==0) 78 e=i; 79 } 80 for (i=1;i<=m;i++) 81 { 82 scanf("%s%s%ld",s1,s2,&d); 83 x=find(s1); 84 y=find(s2); 85 road[x][y]=min(road[x][y],d); 86 road[y][x]=road[x][y]; 87 } 88 for (j=1;j<n;j++) 89 { 90 while (vis[f.top()]) 91 f.pop(); 92 d=f.top(); 93 if (d==e) 94 break; 95 vis[d]=true; 96 for (i=1;i<=n;i++) 97 if (!vis[i]) 98 { 99 if (point[i].dist>point[d].dist+road[i][d]) 100 { 101 pre[i]=d; 102 point[i].count=point[d].count; 103 point[i].dist=point[d].dist+road[i][d]; 104 point[i].free=point[d].free+1; 105 point[i].kill=point[d].kill+kill[i]; 106 f.push(i); 107 } 108 else if (point[i].dist==point[d].dist+road[i][d]) 109 { 110 point[i].count+=point[d].count; 111 if ((point[i].free<point[d].free+1) || 112 (point[i].free==point[d].free+1 && point[i].kill<point[d].kill+kill[i])) 113 { 114 pre[i]=d; 115 point[i].free=point[d].free+1; 116 point[i].kill=point[d].kill+kill[i]; 117 f.push(i); 118 } 119 } 120 } 121 } 122 print(e); 123 printf("\n%ld %ld %ld\n",point[e].count,point[e].dist,point[e].kill); 124 return 0; 125 }