上一篇用到了邻接表,这里学习一下数据结构。
我们知道图的保存方式有很多种,邻接矩阵adjMax【】【】,邻接表。。。。
邻接矩阵适合稠密图,而邻接表在表示稀疏图时很节省内存。
而邻接表又有动态和静态之分,静态和动态就不多做解释了,动态就是有多少用多少,静态你要提前分配好够用的内存,一般会比实际用的大一些。。。。
下面是静态表的一个实例
#include <iostream>
#include <queue>
using namespace std;
const long edge_maxn = 1005; //边的最大上限
const long point_maxn = 105; //点的最大上限
struct node
{/*node存储边,一个edge代表一条边*/
int v; //终点位置
int w; //权值
int next; //同一起点的下一条边存储在edge数组中的位置(理解了这个静态邻接表就可以了)
}edge[edge_maxn];
int pre[point_maxn]; //以该点为起点的第一条边存储在edge数组中的位置
int n; //点的数量
int m; //边的数量
void Init()
{
memset(pre,-1,sizeof(pre));
int Index = 1;
int i,x,y,w;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&w);
edge[Index].v = y;
edge[Index].w = w;
edge[Index].next = pre[x]; //保存x起点的上一条边在edge数组中的位置
pre[x] = Index++; //位置更新
}
}
void print()
{
for(int i=1;i<=n;i++)
{
printf("%d/n",i);
for(int j=pre[i];j!=-1;j=edge[j].next)
{
printf(" -> %d value is %d/n",edge[j].v,edge[j].w);
}
//printf("/n");
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF && (n!=0 || m!=0))
{
Init();
print();
}
return 0;
}
下面是动态表的实例,以poj1511为例
#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
#define MAX_NUM 1000000001
#define MAX_DOTNUM 1000001
int n,m;
queue<int>myqueue;
bool mark[MAX_DOTNUM];
__int64 dis[MAX_DOTNUM];
struct node
{
int v;
int w;
node *next;
}edge[MAX_DOTNUM];//此邻接表用于存储正向图
node reversed_edge[MAX_DOTNUM];//此逆邻接表用于存储逆向图
void initial(node edge[])//邻接表的初始化,里面封装了回收上一次操作所分配之内存的操作
{
int i;
node *p;
node *q;
for(i=1;i<=n;i++)
{
p=&edge[i];
q=p->next;
while(q!=NULL)
{
p->next=q->next;
delete q;
q=p->next;
}
}
}
void input_case()//每一个case的输入函数
{
int i;
for(i=1;i<=m;i++)
{
node *p;
node *q;
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
/**/
p=&edge[a];
q=new node;
q->v=b;
q->w=c;
q->next=p->next;
p->next=q;
/**/
p=&reversed_edge[b];
q=new node;
q->v=a;
q->w=c;
q->next=p->next;
p->next=q;
}
}
void spfa(node edge[])//SPFA部分
{
int i;
/**
memset(mark,false,sizeof(mark));
for(i=1;i<=n;i++)
dis[i]=MAX_NUM;
while(myqueue.size()!=0)
myqueue.pop();
/**
dis[1]=0;
mark[1]=true;
myqueue.push(1);
while(myqueue.size()!=0)//如果队列不空,则进行松弛操作,直到队列空为止
{
int temp=myqueue.front();
myqueue.pop();
mark[temp]=false;
node *p;
for(p=edge[temp].next;p!=NULL;p=p->next)
{
if(dis[p->v]>dis[temp]+p->w)
{
dis[p->v]=dis[temp]+p->w;
if(mark[p->v]!=true)
{
myqueue.push(p->v);
mark[p->v]=true;
}
}
}
}
}
int main()
{
int testcase;
int i,j;
__int64 sum;
scanf("%d",&testcase);
for(i=1;i<=MAX_DOTNUM-1;i++)
{
edge[i].v=i;
edge[i].w=0;
edge[i].next=NULL;
}
for(i=1;i<=MAX_DOTNUM-1;i++)
{
reversed_edge[i].v=i;
reversed_edge[i].w=0;
reversed_edge[i].next=NULL;
}
for(i=1;i<=testcase;i++)
{
sum=0;
scanf("%d%d",&n,&m);
initial(edge);
initial(reversed_edge);
input_case();
spfa(edge);
for(j=1;j<=n;j++)
sum+=dis[j];
spfa(reversed_edge);
for(j=1;j<=n;j++)
sum+=dis[j];
printf("%I64d\n",sum);
}
system("pause");
return 0;
}