HDU 2544 最短路 http://acm.hdu.edu.cn/showproblem.php?pid=2544
题意:计算从1到n的最短时间。
最短路模板题。。。
Source Code:
(Dijkstra):
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int inf=0x3f3f3f3f; const int nv=102; int map[nv][nv]; int dis[nv]; bool s[nv]; int n,m; int dijkstra(int src,int n){ int i,j,u,tmp; for(int i=1;i<=n;i++){ dis[i]=map[src][i]; s[i]=false; } s[src]=true; dis[src]=0; for(i=1;i<n;i++){ tmp=inf; for(j=1;j<=n;j++){ if(!s[j]&&dis[j]<tmp){ tmp=dis[j]; u=j; } } s[u]=true; for(j=1;j<=n;j++){ if(!s[j]&&map[u][j]+dis[u]<dis[j]) dis[j]=map[u][j]+dis[u]; } } return dis[n]; } int main() { while(~scanf("%d %d",&n,&m),n||m){ memset(map,inf,sizeof(map)); while(m--){ int u,v,w; scanf("%d %d %d",&u,&v,&w); if(map[u][v]>w) map[u][v]=map[v][u]=w; } printf("%d\n",dijkstra(1,n)); } return 0; }
(Bellman Ford):
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int inf=0x3f3f3f3f; const int nv=105; struct Edge{ int u,v,w; }gra[nv*nv]; int dis[nv]; void BellmanFord(int n,int m){ memset(dis,inf,sizeof(dis)); dis[1]=0; for(int i=1;i<n;i++){ for(int j=1;j<=m;j++){ if(dis[gra[j].u]+gra[j].w<dis[gra[j].v]) dis[gra[j].v]=dis[gra[j].u]+gra[j].w; if(dis[gra[j].v]+gra[j].w<dis[gra[j].u]) dis[gra[j].u]=dis[gra[j].v]+gra[j].w; } } } int main() { int n,m; while(scanf("%d %d",&n,&m),n+m){ for(int i=1;i<=m;i++){ int u,v,w; scanf("%d %d %d",&u,&v,&w); gra[i].u=u,gra[i].v=v,gra[i].w=w; } BellmanFord(n,m); printf("%d\n",dis[n]); } return 0; }
(spfa):
#include<iostream> #include<cstdio> #include<queue> #include<algorithm> using namespace std; const int maxn=105; const int INF=0x3f3f3f3f; int n,m; int map[maxn][maxn],dis[maxn]; bool mark[maxn]; int Spfa(int src,int des){ for(int i=0;i<=n;i++){ mark[i]=false; dis[i]=INF; } queue<int>Q; mark[src]=true; dis[src]=0; Q.push(src); while(!Q.empty()){ int first=Q.front(); Q.pop(); mark[first]=false; for(int i=1;i<=n;i++){ if(dis[first]+map[first][i]<dis[i]){ if(!mark[i]){ Q.push(i); mark[i]=true; } dis[i]=dis[first]+map[first][i]; } } } return dis[des]; } int main() { while(scanf("%d %d",&n,&m),n+m){ int a,b,c; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++) map[i][j]=INF; } while(m--){ scanf("%d %d %d",&a,&b,&c); if(map[a][b]>c) map[a][b]=map[b][a]=c; } printf("%d\n",Spfa(1,n)); } return 0; }
HDU 1548 A strange lift http://acm.hdu.edu.cn/showproblem.php?pid=1548
题意:一幢N层的楼,每层有一个按钮,可以上或者下X层(当然不能跑到地下或超过楼的层数),问从A层到B层最少按几次按钮。
题解:在纸上画一下很容易想到是单源最短路。由于数据规模很小用BFS亦可。
Source Code:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int inf=0x3f3f3f3f; const int maxn=205; int Map[maxn][maxn],dis[maxn]; bool s[maxn]; int n,a,b; bool OK(int x){ if(x>0&&x<=n) return true; return false; } int dijkstra(int Src,int End){ int i,j,u,tmp; for(i=1;i<=n;i++){ dis[i]=Map[Src][i]; s[i]=false; } s[Src]=true; dis[Src]=0; for(i=1;i<n;i++){ tmp=inf; for(j=1;j<=n;j++){ if(!s[j]&&dis[j]<tmp){ tmp=dis[j]; u=j; } } s[u]=true; for(j=1;j<=n;j++){ if(dis[j]>dis[u]+Map[u][j]) dis[j]=dis[u]+Map[u][j]; } } return dis[End]>=inf?-1:dis[End]; } int main() { while(scanf("%d",&n),n){ scanf("%d %d",&a,&b); memset(Map,inf,sizeof(Map)); int x; for(int i=1;i<=n;i++){ scanf("%d",&x); if(OK(i+x)) Map[i][i+x]=1; if(OK(i-x)) Map[i][i-x]=1; } if(a==b){ printf("0\n"); continue; } if(!OK(a)||!OK(b)){ printf("-1\n"); continue; } printf("%d\n",dijkstra(a,b)); } return 0; }
HDU 2066 一个人的旅行 http://acm.hdu.edu.cn/showproblem.php?pid=2066
题意:一个人想去D个地方,可以从T个地方出发,问到达某个想去的地方的最短时间。
题解:多源最短路,但用Folyd会超时,可以对每个出发点进行单源最短路求法(Dijkstra)。
Source Code:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int inf=0x3f3f3f3f; const int maxn=1005; int Map[maxn][maxn],dis[maxn]; int T,S,D,maxC; bool mark[maxn]; int start[maxn],want[maxn]; void dijkstra(int src){ int i,j,u,tmp; for(i=1;i<=maxC;i++){ dis[i]=Map[src][i]; mark[i]=false; } dis[src]=0; mark[src]=true; for(i=1;i<maxC;i++){ tmp=inf; for(j=1;j<=maxC;j++){ if(!mark[j]&&dis[j]<tmp){ u=j; tmp=dis[j]; } } mark[u]=true; for(j=1;j<=maxC;j++){ if(!mark[j]&&dis[j]>dis[u]+Map[u][j]) dis[j]=dis[u]+Map[u][j]; } } } int main() { //freopen("D:\in.txt","r",stdin); while(scanf("%d %d %d",&T,&S,&D)==3){ memset(Map,inf,sizeof(Map)); maxC=0; int a,b,t,ans=inf; for(int i=1;i<=T;i++){ scanf("%d %d %d",&a,&b,&t); if(Map[a][b]>t) Map[a][b]=Map[b][a]=t; if(a>maxC) maxC=a; if(b>maxC) maxC=b; } for(int i=1;i<=S;i++) scanf("%d",&start[i]); for(int i=1;i<=D;i++) scanf("%d",&want[i]); for(int i=1;i<=S;i++){ dijkstra(start[i]); for(int j=1;j<=D;j++) if(dis[want[j]]<ans) ans=dis[want[j]]; } printf("%d\n",ans); } return 0; }
HDU 2112 HDU Today http://acm.hdu.edu.cn/showproblem.php?pid=2112
题意:求从出发地start到目的地end的最短距离。
分析:用C++ STL中的map将字符串转换成整数,就是典型的最短路了。
Source Code:
#include <iostream> #include <stdio.h> #include <memory.h> #include <string> #include <algorithm> #include <queue> #include <map> using namespace std; const int N = 155; const int INF = 99999999; map<string, int> mp; map<string, bool> bp; int way[N][N], dist[N]; bool visit[N]; string begin, end; int n, ans; void init() //初始化函数 { int i, j; mp.clear(); //清空映射mp bp.clear(); //清空映射bp for(i = 0; i < N; i++) for(j = 0; j < N; j++) if(i == j) way[i][j] = 0; else way[i][j] = INF; } void input() //输入函数 { int i, cost; ans = 1; string str1, str2; cin >> begin >> end; mp[begin] = 1; //mp映射该string为1 bp[begin] = true; //bp映射该string为true if(!bp[end]) { mp[end] = ++ans; bp[end] = true; } for(i = 1; i <= n; i++) { cin >> str1 >> str2 >> cost; if(!bp[str1]) { mp[str1] = ++ans; bp[str1] = true; } if(!bp[str2]) { mp[str2] = ++ans; bp[str2] = true; } way[mp[str1]][mp[str2]] = way[mp[str2]][mp[str1]] = cost; } } void spfa() { int i, now; memset(visit, false, sizeof(visit)); for(i = 0; i <= ans; i++) dist[i] = INF; dist[1] = 0; queue<int> Q; Q.push(1); visit[1] = true; while(!Q.empty()) { now = Q.front(); Q.pop(); visit[now] = false; for(i = 1; i <= ans; i++) { if(dist[i] > dist[now] + way[now][i]) { dist[i] = dist[now] + way[now][i]; if(visit[i] == false) { Q.push(i); visit[i] = true; } } } } } int main() { while(scanf("%d", &n)) { if(n == -1) break; init(); input(); spfa(); if(dist[mp[end]] != INF) printf("%d\n", dist[mp[end]]); else printf("-1\n"); } return 0; }
HDU 1217 Arbitrage http://acm.hdu.edu.cn/showproblem.php?pid=1217
题意:给出几种货币及货币间的汇率,问某种货币是否可以经过兑换其他的货币实现套利(就是兑换了一圈比原来的多)。
分析:多源最短路,结合C++ STL map和Folyd稍作变化即可。
Source Code:
#include <iostream> #include <algorithm> #include <cstring> #include <string> #include <cstdio> #include <queue> #include <map> using namespace std; const double inf=0x3f3f3f3f; const int maxn=50; map<string,int>mp; map<string,bool>bp; bool visit[maxn]; double way[maxn][maxn],dis[maxn]; int n,m,cas=0; double len; bool Floyd(){ for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(way[i][j]<way[i][k]*way[k][j]) way[i][j]=way[i][k]*way[k][j]; } } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(way[i][i]>1) return true; } } return false; } int main() { //freopen("D:\in.txt","r",stdin); while(scanf("%d",&n),n){ string str,str1,str2; for(int i=1;i<=n;i++){ cin>>str; mp[str]=i; } scanf("%d",&m); memset(way,0,sizeof(way)); for(int i=1;i<=m;i++){ cin>>str1>>len>>str2; way[mp[str1]][mp[str2]]=len; } if(Floyd()) printf("Case %d: Yes\n",++cas); else printf("Case %d: No\n",++cas); } return 0; }
HDU 1535 Invitation Cards http://acm.hdu.edu.cn/showproblem.php?pid=1535
题意:有P个站点q条路线,且两个站点之间是单向的。求从1号站点到其他站点的最短路只和+从其他站点回到1号站点的最短路之和。
分析:去的时候求1到其他站点的单源最短路之和即可。对于回来的,是求其他所有站点到1号站点的最短路之和,很自然可以想到将图反向重建,再求1号站点到其他站点的单源最短路即可。
Source Code:
#include<iostream> #include<cstdio> #include<queue> using namespace std; const int N=1000001; const int INF=0x3f3f3f3f; struct node{ int v,w,next; }edgego[N],edgeback[N]; int headgo[N],headback[N],dist[N]; bool mark[N]; int p,q; void spfa(node edge[],int head[]) { memset(mark,false,sizeof(mark)); for(int i=2;i<=p;i++) dist[i]=INF; dist[1]=0; queue<int>Q; Q.push(1); while(!Q.empty()){ int x=Q.front(); Q.pop(); mark[x]=false; for(int e=head[x];e!=-1;e=edge[e].next){ if(dist[edge[e].v]>dist[x]+edge[e].w){ dist[edge[e].v]=dist[x]+edge[e].w; if(!mark[edge[e].v]){ mark[edge[e].v]=true; Q.push(edge[e].v); } } } } } int main() { int t,ans,u,v,w;scanf("%d",&t); while(t--){ ans=0; scanf("%d %d",&p,&q); memset(headgo,-1,sizeof(int)*(p+1)); memset(headback,-1,sizeof(int)*(p+1)); for(int i=1;i<=q;i++){ scanf("%d %d %d",&u,&v,&w); edgego[i].v=v; edgego[i].w=w; edgego[i].next=headgo[u]; headgo[u]=i; edgeback[i].v=u; edgeback[i].w=w; edgeback[i].next=headback[v]; headback[v]=i; } spfa(edgego,headgo); for(int j=2;j<=p;j++) ans+=dist[j]; spfa(edgeback,headback); for(int l=2;l<=p;l++) ans+=dist[l]; printf("%d\n",ans); } return 0; }