题目描述:
Description
设有n个城市,编号为0~n-1,m条单向航线的起点和终点由输入提供,寻找一条换乘次数最少的线路方案。
Input
第一行为三个整数n、m、v,表示城市数、单向航线数和起点城市。以下m行每行两个整数,表示一条边的起点、终点,保证不重复、不失败。2≤n≤20,1≤m≤190
Output
共n-1行,分别是从起点城市v到其他n-1个城市最少换乘次数,按照终点城市序号从小到大顺序输出,不能抵达时输出-1。
Sample Input
3 2 0
0 1
1 2
Sample Output
1
2
#include <iostream>
#include <cstring>
using namespace std;
#define INFTY 99999
class Graph
{
private:
int **a;
int n, e;//n节点,e边
public:
Graph(int m);
~Graph();
void insert(int m);
void output();
bool exist(int num, int v);
int choose(int *d, bool *s);//找最小的距离
void Dijkstra(int v);
};
int main()
{
int n, m, v;//n、m、v,表示城市数、单向航线数和起点城市
cin >> n >> m >> v;
Graph g(n);
g.insert(m);
//g.output();
g.Dijkstra(v);
return 0;
}
Graph::Graph(int m)
{
n = m, e = 0;
a = new int*[n];
for(int i = 0; i < n; i++)
{
a[i] = new int[n];
memset(a[i], 0, n*sizeof(a[i]));
}
}
Graph::~Graph()
{
for(int i = 0; i < n; i++)
{
delete []a[i];
}
delete []a;
}
void Graph::insert(int m)
{
e = m;
int start, end;
for(int i = 0; i < m; i++)
{
cin >> start >> end;
a[start][end] = 1;
}
}
void Graph::output()
{
for(int i = 0; i < n; i++)
{
cout << i << ":";
for(int j = 0; j < n; j++)
cout << a[i][j] << " ";
cout << endl;
}
}
bool Graph::exist(int num, int v)
{
if(a[num][v]) return true;
return false;
}
int Graph::choose(int *d, bool *s)
{
int minPos = -1, min = INFTY;
for(int i = 0; i < n; i++)
{
if((!s[i]) && (d[i] < min))
{
min = d[i];
minPos = i;
}
}
return minPos;
}
void Graph::Dijkstra(int v)//v起点
{
int i, k, *d = new int[n], *path = new int[n];
bool *s = new bool[n];
for(i = 0; i < n; i++)
{
s[i] = false;
if(exist(v, i)) {d[i] = 1, path[i] = v;}
else {d[i] = INFTY, path[i] = -1;}
}
s[v] = true;
d[v] = 0;
for(i = 0; i < n-1; i++)
{
k = choose(d, s);
if(-1 == k) break;
s[k] = true;
for(int j = 0; j < n; j++)
{
if(!s[j] && exist(k, j))
{
if(d[j] > a[v][k]+a[k][j])
{
d[j] = a[v][k] + a[k][j];
path[j] = k;
}
}
}
}
for(i = 0; i < n; i++)
{
if(i != v)
{
if(d[i] != INFTY)
cout << d[i] << endl;
else
cout << "-1" << endl;
}
}
delete []d;
delete []path;
delete []s;
}