这个题目的实质就是一个有向图,权值为正,求某两个节点间的距离,节点需输入。
求解有如下限制,凭记忆,大概如下:
1、两点间关系线少于500,即边少于500,节点数少于25
2、边权值小于100 (设1000为为链接边)
3、另外,输入为Id值,当时觉得比较麻烦的,但想想可以直接
选取条件:
1、路径数(关系线)最短
2、两点间权值和最短。
优先满足1、后2.
分析,因为不存在负权值,可以用Dijkstra算法,维护一个数组dis,记录起始点到某一点的距离即可
算法核心就是 通过边松弛 dis[u] >dis[v]+e[v][u] 则更新dis[u]。
如果要让任意两个点之间的路程变短,只能引入第三个点,并通过这个顶点中转,才能缩短原来两个顶点间距离。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int maxnode = 25;
int nodenum[maxnode];//离散化id
int nodelen[maxnode][maxnode];
//由nodeid值查找
int InNodenum(int nodeid)
{
for(int i=0;i<maxnode;++i)
if(nodeid == nodenum[i])
return i;
return -1;
}
int main()
{
memset(nodenum,0,maxnode*sizeof(int));
//memset(nodelen,1000,maxnode*maxnode*sizeof(int));
for(int i=0;i<maxnode;++i)
for(int j=0;j<maxnode;++j)
if(i==j) nodelen[i][j]=0;
else nodelen[i][j]=1000; //1000表示不连通
int innodenum,innode1id,innode2id,innodelen;
int nodenumco = 0;
vector<int> vout;
cin>>innodenum;
for (int i=0;i<innodenum;++i)
{
cin>>innode1id>>innode2id>>innodelen;
if(-1 == InNodenum(innode1id) )
nodenum[nodenumco++] = innode1id;
if(-1 == InNodenum(innode2id))
nodenum[nodenumco++] = innode2id;
nodelen[InNodenum(innode1id)][InNodenum(innode2id)] = innodelen;
}
int outnodenum,outnode1id,outnode2id;
int *dim = new int[nodenumco];
cin>>outnodenum;
for(int i=0;i<outnodenum;++i)
{
cin>>outnode1id>>outnode2id;
memset(dim,0,nodenumco*sizeof(int));
int locnode1,locnode2;
locnode1 = InNodenum(outnode1id);
locnode2 = InNodenum(outnode2id);
for (int i=0;i<nodenumco;++i)
{
//Dijkstra算法维护数组
dim[i] = nodelen[locnode1][i];
}
//Dijkstra算法核心
for (int i=0;i<nodenumco;++i)
{
if(dim[locnode2]<1000)
{//连接数最少优先
vout.push_back(dim[locnode2]);
break;
}
for(int j=1;j<nodenumco;++j)
if(nodelen[i][j]<1000)
if(dim[j]>dim[i]+nodelen[i][j])
dim[j] = dim[i]+nodelen[i][j];
}
}
delete dim;
for (int i=0;i<vout.size();++i)
{
cout<<vout[i]<<endl;
}
return 0;
}