Article Directory
dijkstra complexity of O (n- 2 )
The basic idea: Shortest: dijkstra algorithm + output path
built side wording: built side - adjacency matrix, vector, star forward chain
- Adjacency matrix and vector versions of:
directly attached to the seniors blog: graph theory basics - Adjacency list (chain-Star forward):
#include <iostream>
#include <string.h>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
typedef long long LL;
using namespace std;
const int manx=1e5+10;
const int INF=0x3f3f3f3f;
int dis[300],vs[300],head[300];
int n,m,cou;
struct node
{
int e,len,bf;//边的终点、边长、和这个点有相同起点的上一条边
} edge[manx<<2];
void add(int s,int e,int len)
{
edge[cou]=node{e,len,head[s]};
head[s]=cou++;
}
void dij(int s,int e)
{
memset(dis,INF,sizeof(dis));
memset(vs,0,sizeof(vs));
vs[s]=1;
dis[s]=0;
int nx=s;
while(!vs[e])
{
for(int i=head[nx]; ~i; i=edge[i].bf)
{
int nlen=edge[i].len;
int ne=edge[i].e;
if(dis[ne]>dis[nx]+nlen)
{
dis[ne]=dis[nx]+nlen;
}
}
nx=-1;//标记距离最小的位置
for(int j=1; j<=n; j++)
{
if(!vs[j])//j点没有走过
if(nx==-1||dis[j]<dis[nx])
nx=j;
}
if(nx==-1)
break;
vs[nx]=1;
}
}
int main()
{
int sx,ex,len,s,e;
while(scanf("%d%d",&n,&m),n||m)
{
cou=1;
memset(head,-1,sizeof(head));
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&sx,&ex,&len);
add(sx,ex,len);
add(ex,sx,len);
}
//scanf("%d%d",&s,&e);
s=1,e=n;
dij(s,e);
if(dis[e]==INF)
{
if(s==e)
printf("0\n");
else
printf("-1\n");
}
else
printf("%d\n",dis[e]);
}
}
1, can think under these three kinds of writing, namely, how complete traversal of all sides have the same starting point of
2, dealt with the results of the apex of what is no path
3, why not solve the edge weight dij have a negative value
Optimization priority queue before the chain to star dij + complexity of O (mlogn)
m is the number of edges in the graph, n is the number of vertices
After optimization with priority queue, the first can be obtained directly from the next vertex team, eliminating the need to traverse the drawing each vertex find a vertex (and in this case if the head of the queue has traversed a vertex, i.e., VS [ pos] = 1, because a node may be put to many times, you can skip later)
Definition of a structure, the data structure contains two: the distance of the vertex to the vertex and the starting point and will be updated and the new vertex distance value into the queue, the priority structure is provided, so that a large distance sink to the tail
Code (not submitted, but the wording is probably like this too):
#include <iostream>
#include <string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
typedef long long LL;
using namespace std;
#define chl (root<<1)
#define chr ((root<<1)|1)
#define mid ((l+r)>>1)
const int manx=1e5+10;
const int INF=0x3f3f3f3f;
int cou=0,head[1010],path[manx][2],dis[1010];
bool vs[1010];
struct node
{
int e,len,bf;
} edge[manx];
void add(int s,int e,int len)
{
edge[cou]=node{e,len,head[s]};
head[s]=cou++;
}
struct poi
{
int pos,len;
};
bool operator<(poi a,poi b)
{
return a.len>b.len;
}
int dij(int s,int e)
{
priority_queue<poi>qu;
memset(dis,INF,sizeof(dis));
memset(vs,0,sizeof(vs));
//vs[s]=1;
dis[s]=0;
int nx=s;
qu.push(poi{s,0});
while(!qu.empty())
{
nx=qu.top().pos;
qu.pop();
//if(vs[nx])
// continue;
vs[nx]=1;
if(vs[e])
break;
for(int i=head[nx]; ~i; i=edge[i].bf)
{
int nlen=edge[i].len;
int ne=edge[i].e;
if(dis[ne]>dis[nx]+nlen)
{
dis[ne]=dis[nx]+nlen;
qu.push(poi{ne,dis[ne]});
}
}
}
return dis[e];
}
int main()
{
int n,m,s,e,ans,a,b,len;
memset(head,-1,sizeof(head));
scanf("%d%d%d%d",&n,&m,&s,&e);
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&a,&b,&len);
path[i][0]=a;
path[i][1]=b;
add(a,b,len);
add(b,a,len);
}
ans=dij(s,e);
printf("%d\n",ans);
}
/*
5 5 1 5
1 2 2
2 3 2
2 4 2
3 5 100
4 5 2*/
An Example: 2872: NO GAME NO LIFE
SPFA desired complexity of O (kE)
E is the number of edges in the graph, k is a constant in many cases not more than 2 k (with reachable without the negative loop)
It can be solved right side there is a negative, and so on up the road dij can not handle.
Star forward chain version:
#include <iostream>
#include <string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
typedef long long LL;
using namespace std;
const int manx=1e5+10;
const int INF=0x3f3f3f3f;
int dis[300],vs[300],head[300];
int n,m,cou;
struct node
{
int e,len,bf;//边的终点、边长、和这个点有相同起点的上一条边
}edge[manx<<2];
void add(int s,int e,int len)
{
edge[cou]=node{e,len,head[s]};
head[s]=cou++;
}
vector<node>vt[300];
int spfa(int s)
{
int c[300];
queue<int>qu;
memset(c,0,sizeof(c));
memset(dis,INF,sizeof(dis));
memset(vs,0,sizeof(vs));
dis[s]=0;
vs[s]=1;
c[s]=1;
//c数组判断是否有负环(并且有从源点到负环的路径),即c[s]是否大于n
qu.push(s);
int sx;
while(!qu.empty())
{
sx=qu.front();//边的起点
qu.pop();
for(int i=head[sx];i;i=edge[i].bf)//i表示边的序号
{
int nx=edge[i].e;
int nlen=edge[i].len;
if(dis[sx]+nlen<dis[nx])
{
dis[nx]=dis[sx]+nlen;
if(!vs[nx])
{
qu.push(nx);
vs[nx]=1;
c[nx]++;//nx被放入队列的次数
if(c[nx]>n)
return 0;
}
}
}
vs[sx]=0;
}
return 1;
}
int main()
{
int sx,ex,len,s,e;
while(scanf("%d%d",&n,&m),n||m)
{
cou=1;
memset(head,0,sizeof(head));
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&sx,&ex,&len);
add(sx,ex,len);
add(ex,sx,len);
}
//scanf("%d%d",&s,&e);
s=1,e=n;
int flag=spfa(s);
if(!flag)
continue;
if(dis[e]==INF)
{
if(s==e)
printf("0\n");
else
printf("-1\n");
}
else
printf("%d\n",dis[e]);
}
}