图论 这里以NKOJ 1120为例
Description
有一无负权有向图。求指定两点间的最短路径。
Input
输入:第一行,两个数字n和m,表示n个顶点,m条边
接下来的m行,每行三个整数,分别表示边的起点、终点和边的长度
最后一行 两个整数 x y 表示求从点x到点y的最短路径
Output
输出:一行,一个整数,最短路径长度
Sample Input
3 3
1 2 5
1 3 2
3 2 1
1 2
Sample Output
3
Hint
注:所有数据都不超过100
//最短路算法均为SPFA====================================================================================================================================
第一种 也就是最粗暴的 邻接矩阵存图
不多解释,这个应该都懂
#include<cstdio>
int n,m,a,y,z;
int map[105][105];
int q[405],dis[105];
void SPFA(int s)
{
bool f[105];
int i,head=1,tail=2,x;
for(i=1;i<=n;i++){dis[i]=99999999;f[i]=false;} //SPFA初始化
q[1]=s;f[s]=true;dis[s]=0;
while(head!=tail)
{
x=q[head++];
f[x]=false;
for(i=1;i<=n;i++)
if (dis[x]+map[x][i]<dis[i])
{
dis[i]=dis[x]+map[x][i];
if (f[i]==false)
{
q[tail++]=i;
f[i]=true;
}
}
}
}
int main()
{
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)//初始化Map数组
for(j=1;j<=n;j++)
if(i!=j)map[i][j]=99999999;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&y,&z);
map[a][y]=z;
}
scanf("%d%d",&a,&z);
SPFA(a);
printf("%d",dis[z]);
return 0;
}
====================================================================================================================================
第二种 临接链表 其实就是多开个V数组来记录每个点的连接情况 v[x][0]表示连接点的个数 后面表示对应的点的编号
#include<cstdio>
#define maxn 105
#define inf 1<<25
int n,m,j,i,x,y,z;
int v[maxn][maxn],Map[maxn][maxn];
int q[maxn*4],dis[maxn];
bool f[maxn];
void _spfa(int s)
{
int i,x,head=1,tail=2;
for(i=1;i<=n;i++)
{
f[i]=false;
dis[i]=inf;
}
dis[s]=0;q[1]=s;f[s]=true;
while(head!=tail)
{
x=q[head++];
f[x]=false;
for(i=1;i<=v[x][0];i++)//v[x][0]表示连接的点的个数 能提前结束循环
{
if(dis[x]+Map[x][v[x][i]]<dis[v[x][i]])
{
dis[v[x][i]]=dis[x]+Map[x][v[x][i]];
if(f[v[x][i]]==false)
{
f[v[x][i]]=true;
q[tail++]=v[x][i];
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i!=j)Map[i][j]=inf;
for(i=1;i<=m;i++)//存入点
{
scanf("%d%d%d",&x,&y,&z);
v[x][0]++;//连接的点的个数
v[x][v[x][0]]=y;//记录其对应的编号
Map[x][y]=z;
}
scanf("%d%d",&x,&y);
_spfa(x);
printf("%d",dis[y]);
return 0;
}
====================================================================================================================================
第三种 边存储 可节省大量空间 效率也比较高
//end[i]记录第i条边的重点,len[i]记录第i条边的长度 ,next[i]表示跟第i条边有相同起点的上一条边的编号,last[x]表示以x为起点的边最新一条的边的编号。
#include<cstdio>
#define maxn 105
#define inf 1<<25
int dis[maxn],len[maxn],end[maxn],next[maxn],last[maxn];
int q[maxn*4];
bool f[maxn];
int n,m,x,y,z;
void _spfa(int s)
{
int i,x,head=1,tail=2;
for(i=1;i<=n;i++)
{
dis[i]=inf;
f[i]=false;
}
dis[s]=0;f[s]=true;q[1]=s;
while(head!=tail)
{
x=q[head++];
f[x]=false;
int k=last[x];
while(k)//以x为起点,k为终点讨论
{
int t=end[k];
if(dis[t]>dis[x]+len[k])
{
dis[t]=dis[x]+len[k];
if(!f[t])
{
f[t]=1;
q[tail++]=t;
}
}
k=next[k];//不要忘记更新k的值
}
}
}
int main()
{
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
end[i]=y;
len[i]=z;
next[i]=last[x];
last[x]=i;
}
scanf("%d%d",&x,&y);
_spfa(x);
printf("%d",dis[y]);
return 0;
}
嗯 存图大概就是这三种 最后一种比较难理解 不过多写即便就好了