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;
}