来源(https://www.cnblogs.com/liyinggang/p/5528944.html)
问题描述
这是春天乡村的N个城市。每对城市之间可能有一条或没有一条交通线。
现在有一些货物应该从一个城市运到另一个城市。
运输费由两部分组成: 这些城市之间的交通成本,以及任何货物通过一个城市时,除来源地和目的地城市外,都要征收一定的税。
您必须编写一个程序来查找成本最低的路线。
输入 第一个是n,城市数量。n=0表示输入结束。
输入中给出了路径成本、城市税、源城市和目的城市的数据,其形式如下:
a11 a12 … a1N
a21 a22 … a2N
…
aN1 aN2 … aNN
b1 b2 … bN
c d
e f
…
g h
其中aij是从城市i到城市j的运输成本,aij=-1表示城市i和城市j之间没有直接路径。bi表示通过城市i的税收。货物将从城市c运送到城市d,城市e运送到城市f,…,g=h=-1。您必须输出经过的城市序列和总成本,其形式为:
Output
From c to d :
Path: c–>c1–>…–>ck–>d
Total cost : …
…
From e to f :
Path: e–>e1–>…–>ek–>f
Total cost : …
注意:如果有更多的最小路径,则输出词汇上最小的路径。在每个测试用例后打印一个空白行。
Sample Input
5
0 3 22 -1 4
3 0 5 -1 -1
22 5 0 9 20
-1 -1 9 0 4
4 -1 20 4 0
5 17 8 3 1
1 3
3 5
2 4
-1 -1
0
Sample Output
From 1 to 3 :
Path: 1–>5–>4–>3
Total cost : 21
From 3 to 5 :
Path: 3–>4–>5
Total cost : 16
From 2 to 4 :
Path: 2–>1–>5–>4
Total cost : 17
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int N=200;
int G[N][N];//记录费用
int path[N][N];//记录途径
int cost[N];
int main()
{
int n;
while(cin>>n&&n)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cin>>G[i][j];
if(G[i][j]==-1) G[i][j]=INF;
path[i][j]=j;
}
for(int i=1;i<=n;i++) cin>>cost[i];
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)//floyed
if(G[i][j]>G[i][k]+G[k][j]+cost[k])
G[i][j]=G[i][k]+G[k][j]+cost[k],path[i][j]=path[i][k];
else if(G[i][j]==G[i][k]+G[k][j]+cost[k]&&path[i][j]>path[i][k])
path[i][j]=path[i][k];//判断修改路径的条件
int a,b;
while(cin>>a>>b)
{
if(a==b&&a==-1) break;
printf("From %d to %d :\nPath: %d",a,b,a);
int u=a,v=b;
while(u!=v)//输出路径
{
printf("-->%d",path[u][v]);
u=path[u][v];
}
printf("\nTotal cost : %d\n\n",G[a][b]);
}
}
return 0;
}
最短路拼接
来源:(https://www.cnblogs.com/wjyyy/p/lg1841.html)
题目描述
参加jsoi冬令营的同学最近发现,由于南航校内修路截断了原来通向计算中心的路,导致去的路程比原先增加了近一公里。而食堂门前施工虽然也截断了原来通向计算中心的路,却没有使路程增加,因为可以找到同样长度的路作替代。其实,问题的关键在于,路截断的地方是交通要点。
同样的情况也出现在城市间的交通中。某些城市如果出了问题,可能会引起其他很多城市的交通不便。另一些城市则影响不到别的城市的交通。jsoi冬令营的同学发现这是一个有趣的问题,于是决定研究这个问题。
他们认为这样的城市是重要的:如果一个城市c被破坏后,存在两个不同的城市a和b(a, b均不等于c),a到b的最短距离增长了(或不通),则城市c是重要的。
jsoi冬令营的同学面对着一张教练组交给他们的城市间交通图,他们希望能找出所有重要的城市。现在就请你来解决这个问题。
输入输出格式
输入格式:
第一行两个整数N,M,N为城市数,M为道路数。
接下来M行,每行三个整数,表示两个城市之间的无向边,以及之间的路的长度。
输出格式:
一行,按递增次序输出若干的数,表示重要的城市。
如果没有点的话需要输出一行
“No important cities.”
去掉引号。
输入输出样例
输入样例#1:
4 4
1 2 1
2 3 1
4 1 2
4 3 2
输出样例#1:
2
说明
30%的数据:N≤20N≤20;
60%的数据:N≤100N≤100;
100%的数据:N≤200,M≤N×(N−1)2,0<c≤10000N≤200,M≤N×(N−1)2,0<c≤10000。cc即路的长度。
保证不出现重边和自环
感谢@赵昕鹏 和@qq2477259579 提供程序
#include<cstdio>
#include<cstring>
#include<bitset>
using std::bitset;
bitset<210> im[210][210];
int f[210][210];
int is[210];
int main()
{
memset(f,0x3f,sizeof(f));
int u,v,n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
f[i][i]=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
scanf("%d",&f[u][v]);
f[v][u]=f[u][v];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
im[i][j][i]=1;//初始化设两端为重要城市
im[i][j][j]=1;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(f[i][k]+f[k][j]==f[i][j])
im[i][j]&=(im[i][k]|im[k][j]);//当更新计数时取交集
else if(f[i][k]+f[k][j]<f[i][j])//当更新最短路时直接赋值为两段的并集
{
f[i][j]=f[i][k]+f[k][j];
im[i][j]=im[i][k]|im[k][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
if(k!=i&&k!=j)//注意特判
if(im[i][j][k])
is[k]=1;
int flag=0;
for(int i=1;i<=n;i++)
if(is[i])
{
flag=1;
printf("%d ",i);
}
if(!flag)//注意判断无解
puts("No important cities.");
return 0;
}