文章目录
HDU2544 最短路
传送门:HDU2544 最短路
解题思路
单源最短路径
AC代码【Dijkstra】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 105;
const int INF = 0x3f3f3f3f;
int n, m;
int dis[MAXN];
vector<pii> edge[MAXN];
priority_queue<pii,vector<pii>,greater<pii> > q;
void dijkstra()
{
// 起点到所有点距离无穷大
memset(dis,INF,sizeof(dis));
dis[1] = 0; // 起点到自己距离为 0
// pair的first优先级高,first存距离,second存点
q.push(pii(0,1));
while (!q.empty())
{
pii t = q.top();
q.pop();
int v = t.second;
// 已经求得的距离更小,就不用操作了(懒惰删除)
if (t.first > dis[v])
{
continue;
}
// 对邻接点进行松弛操作
for (int i = 0; i < edge[v].size(); i++)
{
int p = edge[v][i].first;
int w = edge[v][i].second;
if (dis[p] > dis[v] + w)
{
dis[p] = dis[v] + w;
q.push(pii(dis[p], p));
}
}
}
// 清空图
for (int i = 0; i <= n; i++)
{
edge[i].clear();
}
}
int main()
{
int a, b, c;
while (scanf("%d%d",&n, &m) && n)
{
while (m--)
{
scanf("%d%d%d",&a, &b, &c);
edge[a].push_back(pii(b,c));
edge[b].push_back(pii(a,c));
}
dijkstra();
printf("%d\n",dis[n]);
}
return 0;
}
HDU2066 一个人的旅行
传送门:HDU2066 一个人的旅行
解题思路
可以假设草儿家在0号城市,她到相邻城市的距离为0(或者说直接从相邻城市出发)。跑Dijkstra即可。
AC代码【Dijkstra】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 1005;
const int INF = 0x3f3f3f3f;
int T, S, D;
int dis[MAXN],x[MAXN];
vector<pii> edge[MAXN];
priority_queue<pii,vector<pii>,greater<pii> > q;
void dijkstra()
{
//dis[0] = 0;
//q.push(pii(0,0));
// 直接从几个相邻城市出发
while (!q.empty())
{
pii t = q.top();
q.pop();
int v = t.second;
if (t.first > dis[v])
{
continue;
}
for (int i = 0; i < edge[v].size(); i++)
{
int p = edge[v][i].first;
int w = edge[v][i].second;
if (dis[p] > dis[v] + w)
{
dis[p] = dis[v] + w;
q.push(pii(dis[p], p));
}
}
}
for (int i = 0; i < MAXN; i++)
{
edge[i].clear();
}
}
int main()
{
int a, b, c;
while (~scanf("%d%d%d",&T, &S, &D))
{
while (T--)
{
scanf("%d%d%d",&a, &b, &c);
edge[a].push_back(pii(b,c));
edge[b].push_back(pii(a,c));
}
memset(dis,INF,sizeof(dis));
int ans = INF, nc;
// S 个邻接城市可直达
for (int i = 0; i < S; i++)
{
scanf("%d",&nc);
dis[nc] = 0; // 到邻接城市距离为 0
q.push(pii(0,nc));
}
dijkstra();
for (int i = 0; i < D; i++)
{
scanf("%d",&nc);
// 找想去的 D 个城市中最短的时间
ans = min(ans,dis[nc]);
}
printf("%d\n",ans);
}
return 0;
}
HDU1874 畅通工程续
传送门:HDU1874 畅通工程续
解题思路
求起点到终点距离,单源最短路径。
AC代码【Dijkstra】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 105;
const int INF = 0x3f3f3f3f;
int n, m;
int dis[MAXN];
vector<pii> edge[MAXN];
priority_queue<pii,vector<pii>,greater<pii> > q;
void dijkstra(int strat)
{
memset(dis,INF,sizeof(dis));
dis[strat] = 0;
q.push(pii(0,strat));
while (!q.empty())
{
pii t = q.top();
q.pop();
int v = t.second;
if (t.first > dis[v])
{
continue;
}
for (int i = 0; i < edge[v].size(); i++)
{
int p = edge[v][i].first;
int w = edge[v][i].second;
if (dis[p] > dis[v] + w)
{
dis[p] = dis[v] + w;
q.push(pii(dis[p], p));
}
}
}
for (int i = 0; i <= n; i++)
{
edge[i].clear();
}
}
int main()
{
int a, b, c;
while (~scanf("%d%d",&n, &m))
{
while (m--)
{
scanf("%d%d%d",&a, &b, &c);
edge[a].push_back(pii(b,c));
edge[b].push_back(pii(a,c));
}
int strat, stop;
scanf("%d%d",&strat, &stop);
dijkstra(strat);
printf("%d\n",dis[stop] == INF ? -1:dis[stop]);
}
return 0;
}
HDU2112 HDU Today
解题思路
用map对城市进行唯一编号(将城市名与编号映射起来),然后建立无向图跑最短路即可。
注意事项
1、道路是双向可达的
2、起点和终点可能相同
AC代码1【Floyd】
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 1005;
const int INF = 0x3f3f3f3f;
int n, ind = 0;
int dis[MAXN];
vector<pii> edge[MAXN];
int g[200][200];
map<string,int> mp;
priority_queue<pii,vector<pii>,greater<pii> > q;
void init()
{
for (int i = 0; i < 200; i++)
{
for (int j = 0; j < 200; j++)
{
g[i][j] = INF;
}
g[i][i] = 0;
}
ind = 0;
mp.clear();
}
void floyd()
{
for (int i = 0; i < ind; i++)
{
for (int j = 0; j < ind; j++)
{
for (int k = 0; k < ind; k++)
{
g[j][k] = min(g[j][k], g[j][i] + g[i][k]);
}
}
}
}
int main()
{
IOS
string strat, stop;
string a, b;
int x, y, c;
while (cin >> n && n!= -1)
{
init();
cin >> strat >> stop;
mp[strat] = ind++;
if (!mp.count(stop))
{
mp[stop] = ind++;
}
while (n--)
{
cin >> a >> b >> c;
if (!mp.count(a))
{
mp[a] = ind++;
}
if (!mp.count(b))
{
mp[b] = ind++;
}
x = mp[a], y = mp[b];
// 双向道路且若有重复的道路要取距离小的
g[x][y] = g[y][x] = min(g[y][x], c);
}
floyd();
x = mp[strat], y = mp[stop];
cout << (g[x][y] == INF ? -1 : g[x][y]) << "\n";
}
return 0;
}
AC代码2【Dijkstra】
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 1005;
const int INF = 0x3f3f3f3f;
int n, ind = 0;
int dis[MAXN];
vector<pii> edge[MAXN];
map<string,int> mp;
priority_queue<pii,vector<pii>,greater<pii> > q;
void init()
{
for (int i = 0; i < ind; i++)
{
edge[i].clear();
}
ind = 0;
mp.clear();
}
void dijkstra(int strat)
{
memset(dis,INF,sizeof(dis));
dis[strat] = 0;
q.push(pii(0,strat));
while (!q.empty())
{
pii t = q.top();
q.pop();
int v = t.second;
if (t.first > dis[v])
{
continue;
}
for (int i = 0; i < edge[v].size(); i++)
{
int p = edge[v][i].first;
int w = edge[v][i].second;
if (dis[p] > dis[v] + w)
{
dis[p] = dis[v] + w;
q.push(pii(dis[p], p));
}
}
}
}
int main()
{
IOS
string strat, stop;
string a, b;
int x, y, c;
while (cin >> n && n!= -1)
{
cin >> strat >> stop;
mp[strat] = ind++;
if (!mp.count(stop))
{
mp[stop] = ind++;
}
while (n--)
{
cin >> a >> b >> c;
if (!mp.count(a))
{
mp[a] = ind++;
}
if (!mp.count(b))
{
mp[b] = ind++;
}
x = mp[a], y = mp[b];
// 无向图
edge[x].push_back(pii(y,c));
edge[y].push_back(pii(x,c));
}
x = mp[strat], y = mp[stop];
dijkstra(x);
cout << (dis[y] == INF ? -1 : dis[y]) << "\n";
init();
}
return 0;
}
HDU1385 Minimum Transport Cost
传送门:HDU1385 Minimum Transport Cost
题目大意
给定一个N表示有N个城市,接下来的N行每行N个数描述了两两城市之间的路费(-1表示两个城市没有直接路径),然后给定一行N个数表示每个城市的收费。接下来会有一些询问。
问:对于给定城市a和b,从a到b花费的最少费用为多少(费用为路费+经过城市的收费,起点和终点不收费),并给出路径。如果有相同的最短路径值,路径按字典序输出。
解题思路
由于给定的询问城市是任意的,可以当做多源最短路处理。用Floyd计算任意两个城市之间的最短路径,并在过程中记录中转点便于后期输出路径。
AC代码【Floyd】
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 300;
const int INF = 0x3f3f3f3f;
int n;
int g[MAXN][MAXN],cost[MAXN],path[MAXN][MAXN];
void floyd()
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
for (int k = 1; k <= n; k++)
{
// 通过 i 城市中转的花费
int w = g[j][i] + g[i][k] + cost[i];
// 若通过 i 城市中转花费更少
if (g[j][k] > w)
{
g[j][k] = w;
// j -> k = j -> i -> k, j -> i = .....
path[j][k] = path[j][i];
}
// 花费相同时保证路径按字典序顺序
else if (g[j][k] == w)
{
path[j][k] = min(path[j][i], path[j][k]);
}
}
}
}
}
// 打印路径
void output(int s, int e)
{
printf("Path: ");
int temp = s;
while(temp != e)
{
printf("%d-->",temp);
temp = path[temp][e];
}
printf("%d\n",e);
}
int main()
{
int a, b, c;
while(~scanf("%d",&n) && n)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
scanf("%d",&c);
path[i][j] = j; // 初始化
g[i][j] = (c == -1 ? INF:c);
}
}
for (int i = 1; i <= n; i++)
{
scanf("%d",&cost[i]);
}
floyd();
while (scanf("%d%d",&a, &b) && a != -1)
{
printf("From %d to %d :\n",a, b);
output(a,b);
printf("Total cost : %d\n\n",g[a][b]);
}
}
return 0;
}