作为 在图论中的基础就是打邻接表,用来存储点与点之间的关系,常用的操作就是直接开二维数组,然后双重for循环,判断关系,直接打出来,但是这样的操作并不适合所有情况,当点剧集密度比较大(稠密图)
,数据范围不太大,时间要求不高的时候适合,因为可能会RE或者LT.。所以慢慢就有了两种更加合适的邻接表表示方式,vector 和 静态链表。
我一开始超喜欢开二维数组表示邻接矩阵,但是在某些题目中,会让你修改到怀疑人生,所以,一上来就用后两种,会减少后期因为时间 数据范围等不合适造成的错误。
vector表示邻接表:(vector 可以自己开不定长度的数组,利用这个特性,来达到空间最优)
struct node{
int id;
int d;
};
vector<node> q[maxn];
void init(int n)//初始化q数组
{
for(int i=0;i<=n;i++)
q[i].clear();
}
void add(int x,int y,int d)
{//将t压入q数组
node t;
t.id=y;
t.d=d;
q[x].push_back(t);//压入数组尾部
}
for(int i=0;i<q.size();i++)
{
int v=q[i].id;
int d=q[i].d;
}
虽然知道这个vector,但是,,作为小白的我,很少用过它,更喜欢用静态链表,因为用起来舒坦
struct node{
int id;
int d;
int next;
}side[maxn];
void init()
{
memset(head,-1,sizeof(head));
cnt=0;
}
void add(int x,int y,int d)
{
side[cnt].id=y;
side[cnt].d=d;
side[cnt].next=head[x];
head[x]=cnt++;
}
for(int j=head[i];j!=-1;j=side[j].next)
{
int v=side[j].d;
int u=side[j].id;
}//实质是头插
有了邻接表之后,就可以自然的进阶实现拓扑排序,还是以静态链表实现
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define maxn 10000
using namespace std;
int n,m,cnt;
int head[maxn];
int in[maxn];
int ans[maxn];
struct node{
int id;
int d;
int next;
}side[maxn];
void init()
{
memset(head,-1,sizeof(head));
cnt=0;
}
void add(int x,int y,int d)
{
side[cnt].id=y;
side[cnt].d=d;
side[cnt].next=head[x];
head[x]=cnt++;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
// memset(mark,0,sizeof(mark));
init();
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b,0);
//in[a]++;
in[b]++;
}
priority_queue<int,vector<int>,greater<int> > pq;
for(int i=1;i<=n;i++)
if(in[i]==0)
pq.push(i);
int k=0;
while(pq.size())
{
int x=pq.top();
ans[k++]=x;
pq.pop();
for(int j=head[x];j!=-1;j=side[j].next)
{
int y=side[j].id;
in[y]--;
if(in[y]==0) pq.push(y);
}
}
for(int i=0;i<k;i++)
printf("%d ",ans[i]);
}
return 0;
}
并不是什么ac代码,只是敲的实例而已,拓扑排序,重要的是要掌握对优先队列的处理.
priority_queue默认为大顶堆,即堆顶元素为堆中最大元素。如果我们想要用小顶堆的话需要增加使用两个参数:priority_queue<int, vector<int>, greater<int> > q; // 小顶堆//升序
priority_queue<int, vector<int>, less<int> > q; // 大顶堆//降序