在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
2 1 1 2 3 3 3 1 2 5 2 3 5 3 1 2 0 0
3 2
/******************************* Floyd ******************************/
#include <stdio.h>
#define INF 0x7FFFFFFF
int dist[100][100];
int main() {
int N, M;
while (~scanf("%d%d", &N, &M)) {
if (!N && !M)break;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if(i!=j)dist[i][j] = INF;
else dist[i][j] = 0;
}
}
int a, b, cost;
while (M--) {
scanf("%d%d%d", &a, &b, &cost);
dist[a-1][b-1] = dist[b-1][a-1] = cost;
}
for (int k = 0; k < N; k++) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if ((dist[i][k] == INF || dist[k][j] == INF)||(i==j))continue;
dist[i][j] = dist[i][j] < dist[i][k] + dist[k][j] ? dist[i][j] : dist[i][k] + dist[k][j];
}
}
}
printf("%d\n", dist[0][N - 1]);
}
return 0;
}
/******************************* Dijkstra ******************************/
#include <stdio.h>
#include <memory.h>
#define INF 0x7FFFFFFF
int dist[100][100];
bool flag[100];
int main() {
int N, M;
while (~scanf("%d%d", &N, &M)) {
if (!N && !M)break;
memset(flag, false, N);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if(i!=j)dist[i][j] = INF;
else dist[i][j] = 0;
}
}
int a, b, cost;
while (M--) {
scanf("%d%d%d", &a, &b, &cost);
dist[a-1][b-1] = dist[b-1][a-1] = cost;
}
flag[0] = true;
int min, tmp = 1;
for (int i = 1; i < N; i++) {
min = INF;
for (int j = 1; j < N; j++) {
if (flag[j])continue;
if (dist[0][j] < min) {
min = dist[0][j];
tmp = j;
}
}
flag[tmp] = true;
if (tmp == N - 1)break;
for (int j = 1; j < N; j++) {
if (flag[j]||dist[tmp][j]==INF)continue;
if (dist[0][tmp] + dist[tmp][j] < dist[0][j])dist[0][j] = dist[0][tmp] + dist[tmp][j];
}
}
printf("%d\n", dist[0][N - 1]);
}
return 0;
}
#include<stdio.h>
int ans[101][101];
int main() {
int n,m;
while (scanf("%d%d", &n,&m) != EOF){
if (n == 0 || m == 0)break;
for(int i=1;i<=n;i++){
for (int j = 1; j <= n; j++)
ans[i][j] = -1;
ans[i][i] = 0;
}//初始化;
int a, b, c;
while(m--) {
scanf("%d%d%d", &a, &b, &c);
ans[a][b] = ans[b][a] = c;
}//赋值
for(int k=1;k<=n;k++){
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (ans[i][k] == -1 || ans[k][j] == -1) continue;
if (ans[i][j] == -1 || ans[i][j] > ans[i][k] + ans[k][j])
ans[i][j] = ans[i][k] + ans[k][j];
}
}
}
printf("%d\n", ans[1][n]);
}
return 0;
}
//Floyd算法
#include<bits/stdc++.h>
using namespace std;
int ans[102][102];
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(m==0&&n==0) break;
for(int i=1;i<=n;i++)//初始化图的邻接矩阵
{
for(int j=1;j<=n;j++)
ans[i][j]=-1;
ans[i][i]=0;
}
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
ans[a][b]=c;
ans[b][a]=c;
}
//floyd算法
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(ans[i][k]==-1||ans[k][j]==-1) continue;
else if(ans[i][j]==-1 || ans[i][j]>ans[i][k]+ans[k][j])
ans[i][j]=ans[i][k]+ans[k][j];
}
}
}
cout<<ans[1][n]<<endl;
}
return 0;
}
邻接矩阵实现的 Dijkstra, Floyd, Bellman-Ford 大礼包
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
int dijkstra(vector<vector<int>> &adjMatrix, int n, int m, int s, int t) {
// n 个点,m 条边
vector<bool> isFixed(n + 1, false);
vector<int> dist(n + 1, INT_MAX);
// 初始化 dist 数组,表示各点到原点的最短距离
for (int i = 1; i <= n; ++i)
dist[i] = adjMatrix[1][i];
// 初始化点集合信息,将 1 号点标记为 true
isFixed[s] = true;
// dijkstra
for (int i = 1; i < n; ++i) { // 总共会处理 n-1 个点
// 1. 找到当前 dist 数组中未加入解集点中到起点距离最小的点
// 这里可以使用堆结构进行优化
int minDist = INT_MAX;
int minVertex = 1;
for (int i = 0; i <= n; ++i) {
if (dist[i] < minDist && isFixed[i] == false) {
minDist = dist[i];
minVertex = i;
}
}
// 2. 将该点加入解集
isFixed[minVertex] = true;
// 3. 松弛该点的邻接边
// 这里可以使用邻接表优化
for (int j = 1; j <= n; ++j) {
if (adjMatrix[minVertex][j] < INT_MAX) {
dist[j] = min(dist[j], dist[minVertex] + adjMatrix[minVertex][j]);
}
}
}
return dist[t];
}
int floyd(vector<vector<int>> &adjMatrix, int n, int m, int s, int t) {
// 通过前 k 个点进行中转
for (int k = 1; k <= n; ++k) {
// i->j 的最短路
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
// 若中途有路径不可达则跳过
if (i == j || adjMatrix[i][k] == INT_MAX || adjMatrix[k][j] == INT_MAX)
continue;
// 否则选择更短的路径
adjMatrix[i][j] = min(adjMatrix[i][j], adjMatrix[i][k] + adjMatrix[k][j]);
}
}
}
return adjMatrix[s][t];
}
int bellmanFord(vector<vector<int>> &adjMatrix, int n, int m, int from, int to) {
// n 个点,m 条边(这里使用邻接矩阵,m 没用上)
// 初始化 dist 数组,表示各点到原点的最短距离
vector<int> dist(n + 1, INT_MAX);
dist[from] = 0;
// 对所有的 m 条边都进行 n-1 轮松弛 O(V)
for (int i = 1; i < n; ++i) {
bool relaxed = false;
// 每轮松弛所有的边,由于采用了邻接矩阵表示,因此只能遍历二维矩阵 O(E)
// 因此这里采用邻接表表示会更方便
for (int s = 1; s <= n; ++s) {
for (int t = 1; t <= n; ++t) {
// 跳过不存在的边
if (s == t || adjMatrix[s][t] == INT_MAX) continue;
// 松弛边,也就是松弛边的 to 节点
if (dist[s] != INT_MAX && dist[t] > dist[s] + adjMatrix[s][t]) {
dist[t] = dist[s] + adjMatrix[s][t];
relaxed = true;
}
}
}
// 如果这一轮没有发生松弛,则找到所有最短路,提前终止
if (relaxed == false) break;
}
return dist[to];
}
int main() {
// 输入图的点数和边数
// 点表示为 1,2,3,...,N
int v, e;
while (cin >> v >> e && (v != 0 && e != 0)) {
int n = v, m = e;
// 图的邻接矩阵
vector<vector<int>> adjMatrix(v + 1, vector<int>(v + 1, INT_MAX));
// 初始化邻接矩阵
for (int i = 1; i <= v; ++i)
adjMatrix[i][i] = 0;
// 每条边的起点,终点和花费
int s, t, c;
while (e--) {
cin >> s >> t >> c;
// 这里是无向图,需要更新两个方向
// 如果是有向图就只需要更新输入的方向就行了
adjMatrix[s][t] = c;
adjMatrix[t][s] = c;
}
// 将图和求解目标输入算法求解
int opt = dijkstra(adjMatrix, n, m, 1, n);
// int opt = floyd(adjMatrix, n, m, 1, n);
// int opt = bellmanFord(adjMatrix, n, m, 1, n);
cout << opt << endl;
}
return 0;
}
#include<iostream>
#include<vector>
#include<limits.h>
#define N 101
using namespace std;
struct edge{ //邻接表边节点
int next;
int time;
};
vector<edge> Edges[N];
bool mark[N];//标记已经是最短路径的点
int dis[N]; //保存1号点到其他各个点的最短距离
void init(int n){
for(int i=1;i<=n;i++){
dis[i]=-1; //-1表示无穷
mark[i]=false; //未扩展
}
}
int main(){
int n,m;
int a,b,t;
while(cin>>n>>m){
if(n==0&&m==0) break;
for(int i=1;i<N;i++){
Edges[i].clear();//初始化,清空容器中的内容
}
for(int i=1;i<=m;i++){ //创建无向图邻接表
cin>>a>>b>>t;
edge temp;
temp.time=t;
temp.next=b;
Edges[a].push_back(temp);
temp.next=a;
Edges[b].push_back(temp);
}
init(n);//初始化距离数组以及标记数组
int p=1; //p保存当前选择节点,从1号点开始
int x=n-1;
dis[p]=0;
mark[p]=true;
while(x--){ //加入n-1次节点
int min=INT_MAX;
for(int j=0;j<Edges[p].size();j++){//对所有与当前节点相接的节点k尝试进行松弛操作
int k=Edges[p][j].next;
if(mark[k]==true) continue;//已经是最短路径集合中的点,跳过
if(dis[k]==-1||dis[p]+Edges[p][j].time<dis[k]){ //比较大小,更新最短距离
dis[k]=dis[p]+Edges[p][j].time;
}
}
for(int i=1;i<=n;i++){
if(mark[i]==false&&dis[i]!=-1&&dis[i]<min){ //选择待扩展点中距离最短的点加入集合中
min=dis[i];
p=i;
}
}
mark[p]=true;
}
cout<<dis[n]<<endl;
}
return 0;
}
Dijstra算法,时间复杂度为o(n*n)
#include <iostream>
using namespace std;
const int maxn = 100+5;
int arr[maxn][maxn];
int main() {
int n, m;
while (cin >> n >> m) {
if (n == 0 && m == 0) break;
//初始化,所有节点之间不可达
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
arr[i][j] == -1;
}
arr[i][i] = 0;
}
while (m--) {
int a, b, c;
cin >> a >> b >> c;
arr[a][b] = c;
arr[b][a] = c;
}
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (arr[i][k] == -1 || arr[k][j] == -1) continue;
if (arr[i][j] == -1 || (arr[i][k]+arr[k][j]) < arr[i][j]) {
arr[i][j] = arr[i][k] + arr[k][j];
}
}
}
}
cout << arr[1][n] << endl;
}
return 0;
}
#include<stdio.h>
#include<vector>
#define INF 0x7FFFFFFF //设置一个int的最大值,之后用于赋值给min来进行比较
using namespace std;
struct Edge
{
int next;
int cost;
};
vector<Edge> edge[101]; /*这里用了vector,也就是说用邻接表法来构造图,
vector用法可以访问Cplusplus.com,为统一起见
定义101个表头。*/
int main()
{
int dis[101]; /*定义起始点到终点的距离,mark表示集合,每得到
一个点的最短路径,就加入mark[]中*/
bool mark[101]; //因为一会儿以i=1开始访问节点,所以定义101个
int n,m;
while(scanf("%d%d",&n,&m) != EOF) //输入路口数,和路径数
{
if(n == 0 && m == 0) //为0结束程序
break;
for(int i = 0; i<n; i++) //对vector初始化
edge[i].clear();
for(int i = 0; i<m; i++) //输入边的信息
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
Edge temp;
temp.cost = c;
temp.next = a;
edge[b].push_back(temp);
temp.next = b;
edge[a].push_back(temp);
}
for(int i = 1; i<=n ;i++)
{
mark[i] = false;
dis[i] = -1;
}
int newPoint = 1; //newPoint用于存放每次新加入的点
mark[newPoint] = true; //把第一个点设为起始点,先加入集合中
dis[newPoint] = 0;
for(int i = 1; i<n; i++) //对剩余点进行遍历
{ for(int j = 0; j<edge[newPoint].size(); j++) //遍历当前点所连接的所有边
{
int next = edge[newPoint][j].next;
int cost = edge[newPoint][j].cost;
if(mark[next] == true) //如果该边所连接的点已在集合中,不做处理
continue;
if(dis[next] == -1 || cost + dis[newPoint]<dis[next])//前一句dis[next]==-1说明当前遍历到的边,其next所指示的点
{ //是之前无法到达的,或者有更短的路
dis[next] = cost + dis[newPoint];
}
}
int min = INF;
for(int j = 1; j<=n; j++)
{
if(mark[j])
continue;
if(dis[j] == -1)
continue;
if(min>dis[j]) //找到本次遍历中找到的最短路
{
min = dis[j];
newPoint = j; //暂定最小值点,如有更小的会更新
}
}
mark[newPoint] = true; //上一个for结束后,newPoint即为新加的点
}//主要循环
printf("%d\n",dis[n]);
}//while
return 0;
}
#include<stdio.h>
#define N 101
int ans[N][N];
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
if(n==0&&m==0) break;
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
ans[i][j]=-1;
while(m--){
int a,b,tmp;
scanf("%d%d%d",&a,&b,&tmp);
ans[a][b]=tmp;
ans[b][a]=tmp;
}
int k;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
if(ans[i][k]==-1||ans[k][j]==-1) continue;
if(ans[i][j]==-1||ans[i][k]+ans[k][j]<ans[i][j])
ans[i][j]=ans[i][k]+ans[k][j];
}
printf("%d\n",ans[1][n]);
}
return 0;
}
import java.util.*; public class Dijkstra{ static class Node{ int value; ArrayList<Node> nodes; ArrayList<Edge> edges; Node(int value){ this.value = value; nodes = new ArrayList<>(); edges = new ArrayList<>(); } @Override public String toString() { String res=value+":"; for(Node node:nodes){ res += node.value+" "; } res+="\n"; return res; } } static class Edge{ Node from; Node to; int cost; Edge(Node from,Node to,int cost){ this.from = from; this.to = to; this.cost = cost; } } public static void main(String[] args) { Scanner in = new Scanner(System.in); while (in.hasNext()) { int n = in.nextInt(); int m = in.nextInt(); if(n==0&&m==0){ break; } HashMap<Integer,Node> nodes = new HashMap<>(); HashSet<Edge> edges = new HashSet<>(); for(int i=1;i<=m;i++){ int from = in.nextInt(); int to = in.nextInt(); int cost = in.nextInt(); if(!nodes.containsKey(from)){ nodes.put(from,new Node(from)); } if(!nodes.containsKey(to)){ nodes.put(to,new Node(to)); } Node fromNode = nodes.get(from); Node toNode = nodes.get(to); Edge edge = new Edge(fromNode,toNode,cost); Edge edge2 = new Edge(toNode,fromNode,cost); fromNode.nodes.add(toNode); fromNode.edges.add(edge); fromNode.edges.add(edge2); toNode.nodes.add(fromNode); toNode.edges.add(edge); toNode.edges.add(edge2); } HashMap<Node,Integer> distanceMap = new HashMap<>(); HashSet<Node> selectedNodes = new HashSet<>(); Node head = nodes.get(1); distanceMap.put(head,0); Node minNode = getMinDistanceAndUnselectedNode(distanceMap,selectedNodes); while (minNode!=null){ int distance = distanceMap.get(minNode); for(Edge edge:minNode.edges){ Node toNode = edge.to; if(!distanceMap.containsKey(toNode)){ distanceMap.put(toNode,distance+edge.cost); } distanceMap.put(toNode,Math.min(distanceMap.get(toNode),distance+edge.cost)); } selectedNodes.add(minNode); minNode = getMinDistanceAndUnselectedNode(distanceMap,selectedNodes); } System.out.println(distanceMap.get(nodes.get(n))); } } private static Node getMinDistanceAndUnselectedNode( HashMap<Node, Integer> distanceMap, HashSet<Node> selectedNodes) { Node minNode = null; int minDistance = Integer.MAX_VALUE; for(Map.Entry<Node,Integer> entry:distanceMap.entrySet()){ Node node = entry.getKey(); int distance = entry.getValue(); if(!selectedNodes.contains(node)&&distance<minDistance){ minNode = node; minDistance = distance; } } return minNode; } }
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=10005;
const int INF=1e7;
struct edge{
int from,to,cost;
};
edge es[2*maxn];
int N,M,d[maxn];
void shortest_path(int s){
fill(d,d+N+1,INF);
d[1]=0;
while(true){
bool ok=false;
for(int i=1;i<=2*M;i++){
edge e1=es[i];
if(d[e1.from]!=INF&&d[e1.to]>d[e1.from]+e1.cost){
d[e1.to]=d[e1.from]+e1.cost;
ok=true;
}
}
if(!ok) break;
}
}
int main(){
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&N,&M)==2&&N){
for(int i=1;i<=M;i++){
scanf("%d%d%d",&es[2*i-1].from,&es[2*i-1].to,&es[2*i-1].cost);
es[2*i].from=es[2*i-1].to;
es[2*i].to=es[2*i-1].from;
es[2*i].cost=es[2*i-1].cost;
}
shortest_path(1);
printf("%d\n",d[N]);
}
return 0;
}
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=105;
const int INF=1e6;
bool vis[maxn];
int d[maxn];
int cost[maxn][maxn];
int n,m;
void shortest_path(){
while(true){
int v=-1;
for(int u=1;u<=n;u++){
if(!vis[u]&&(v==-1||d[u]<d[v]))
v=u;
}
if(v==-1) break;
vis[v]=true;
for(int u=1;u<=n;u++){
d[u]=min(d[u],d[v]+cost[v][u]);
}
}
}
void init(){
fill(vis,vis+n+1,false);
fill(d,d+n+1,INF);
d[1]=0;
for(int i=1;i<=n;i++){
fill(cost[i],cost[i]+n+1,INF);
}
}
int main(){
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&m)==2&&n){
int from,to,c;
init();
for(int i=1;i<=m;i++){
scanf("%d%d%d",&from,&to,&c);
cost[from][to]=cost[to][from]=c;
}
shortest_path();
printf("%d\n",d[n]);
}
return 0;
}
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define INF 1000000 using namespace std; int city,road; int mapp[205][205]; int spand[205]; int select[205]; void dij(int city) { int minn,k,i,j; memset(select,0,sizeof(select)); for(i=1;i<=city;i++) spand[i]=mapp[1][i]; spand[1]=0;select[1]=1; for(i=2;i<=city;i++) { minn=INF;k=-1; for(j=1;j<=city;j++) { if(!select[j]&&spand[j]<minn) { k=j;minn=spand[j]; } } if(k==-1)break; select[k]=1; for(j=1;j<=city;j++) { if(spand[j]>spand[k]+mapp[k][j]&&!select[j]) spand[j]=spand[k]+mapp[k][j]; } } printf("%d\n",spand[city]); } int main() { int i;int x,y,z; while(scanf("%d%d",&city,&road)!=EOF) { if(city==0||road==0) break; memset(mapp,INF,sizeof(mapp)); memset(spand,INF,sizeof(spand)); for(i=1;i<=road;i++) { scanf("%d%d%d",&x,&y,&z); if(mapp[x][y]>z||mapp[y][x]>z) { mapp[x][y]=z;mapp[y][x]=z; } } dij(city); } return 0; }