floyd
判断连通性
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mp[i][j]=mp[i][j]||(mp[i][k]&&mp[k][j]);
//if(mp[i][j]||(mp[i][k]&&mp[k][j]))
mp[i][j]=true;
求最短路径
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mp[i][j]>mp[i][k]+mp[k][j])
mp[i][j]=mp[i][k]+mp[k][j]);
dijkstra
/*
5 7
1 2 3
1 5 7
1 4 2
2 3 1
2 5 8
3 4 7
4 5 4
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e2+5;
const int inf=0x7f7f7f7f;
int maxn,n;//maxn为结点个数,n为边的条数
int mp[N][N],dis[N];//dis即为最短路径
void dijkstra(int v0)
{
//初始化,以v0为起点
bool s[maxn];//用于存储已经走过的结点
for(int i=1;i<=maxn;i++){
s[i]=false;
dis[i]=mp[v0][i];
}
s[v0]=true;
dis[v0]=0;
//
for(int i=2;i<=maxn;i++){//已经走过一个结点,所以从2开始
int mindis=inf,u;//u为下一步走的结点
for(int j=1;j<=maxn;j++){
if(!s[j]&&dis[j]<mindis){
u=j;mindis=dis[j];
}
}
s[u]=true;//该结点已经走过
//更新最短路径及距离
for(int j=1;j<=maxn;j++)
if(!s[j]&&mp[u][j]<inf) dis[j]=min(dis[j],dis[u]+mp[u][j]);
//mp[u][j]<inf可以防止溢出
}
}
int main()
{
memset(mp,0x7f,sizeof(mp));
scanf("%d%d",&maxn,&n);
for(int i=0;i<n;i++)
{
int x,y,value;
scanf("%d%d%d",&x,&y,&value);
mp[x][y]=value;
mp[y][x]=value;//无向网图
}
int v;//原点
scanf("%d",&v);
dijkstra(v);
for(int i=1;i<=maxn;i++)
printf("%d ",dis[i]);
return 0;
}
用vector存图的dijkstra
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int inf=0x3f3f3f3f;
struct node{
int ed,len;
node(){}
node(int ed,int len):ed(ed),len(len){}
};
vector<node>E[105];
int main()
{
ios::sync_with_stdio(false);
int n,m;
while(cin>>n>>m){
if(n==0&&m==0)
break;
for(int i=0;i<105;i++)
E[i].clear();
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
E[a].push_back(node(b,c));
E[b].push_back(node(a,c));
}
bool s[105];
int dis[105];
memset(s,0,sizeof s);
memset(dis,0x3f,sizeof dis);
for(int i=0;i<E[1].size();i++)
dis[E[1][i].ed]=E[1][i].len;
dis[1]=0;
s[1]=true;
for(int i=2;i<=n;i++){
int u,mindis=inf;
for(int j=1;j<=n;j++){
if(!s[j]&&dis[j]<mindis){
u=j;
mindis=dis[j];
}
}
s[u]=true;
for(int j=0;j<E[u].size();j++)
if(!s[E[u][j].ed])
dis[E[u][j].ed]=min(dis[E[u][j].ed],dis[u]+E[u][j].len);
}
cout<<dis[n]<<endl;
}
return 0;
}
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
struct node{
int ed,len,next;
}e[20050];
int p[105],num;
void add(int st,int ed,int len)
{
e[num].ed=ed;
e[num].len=len;
e[num].next=p[st];
p[st]=num;
num++;
}
int main()
{
ios::sync_with_stdio(false);
int n,m;
while(cin>>n>>m){
if(n==0&&m==0)
break;
memset(e,-1,sizeof e);
memset(p,-1,sizeof p);
num=0;
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);
}
bool s[105];
int dis[105];
memset(dis,0x3f,sizeof dis);
memset(s,0,sizeof s);
dis[1]=0;
for(int i=1;i<=n;i++){
int mindis=inf,u;
for(int j=1;j<=n;j++){
if(!s[j]&&dis[j]<mindis){
u=j;
mindis=dis[j];
}
}
s[u]=true;
for(int j=p[u];j!=-1;j=e[j].next){
if(!s[e[j].ed])
dis[e[j].ed]=min(dis[e[j].ed],dis[u]+e[j].len);
}
}
cout<<dis[n]<<endl;
}
return 0;
}
vector存图可以减少内存开销
Struct node{
int en,len;
};
Vector E[num]; //num为点的个数。
其中E[u][j]表示结点u到结点j的路径
邻接表也可以减少内存开销
Struct node
{
int en,len,next;
}E[MAXM];
Int p[MAXN],num;
用结构体数组存下所有的边权,下一节点。
借助p数组标记,节点id,在E数组中的首位置。
初始化
Void init()
{
Memset(p,-1,sizeof(p));
Num=0;//num是存入E的第几条边
}
加边
Void add(int st,int en,int len)
{
E[num].en=en;
E[num].len=len;
E[num].next=p[st];//头插法
P[st]=num;
num++;
}
每次加边,可得以st为首节点,它邻接点存的位置p[st]。
遍历结点
For(i=p[u];i!=-1;i=E[i].next)
{
int v=E[i].en;
int length=E[i].len;
//i的初值为u点的第一个临界点在E[]数组的下标。然后i=E[i].next,递推找到下一个u的邻接点。知道为-1(p的初值)
}