邻接表(vector e[100]; e[x].push_back( (node){y,z} ); node(int a,int b):y(a),z(b){};)

 

struct node
{
    int y,z;
    node(int a,int b):y(a),z(b){};
};

vector e[100];//邻接表
 for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
       e[x].push_back( (node){y,z} );
       //e[y].push_back((node){x,z});
    //存入无向图
    }

对第一种方法有种优化就是对每个点所对应的边的向量进行预估。例如有m条有向边,n个点,那么每个向量需要reserve(6*(m/n)/5);一般这样存储效率会有显著提高。

#include 
#include 
using namespace std;
int main()
{
    vector> graph(5);
    graph[0].push_back(1);//V0->V1.
    graph[1].push_back(4);//V1->V4.
    graph[1].push_back(0);//V1->V0.
    graph[2].push_back(1);//V2->V1.
    graph[2].push_back(3);//V2->V3.
    graph[3].push_back(0);//V3->V0.
    graph[4].push_back(3);//V4->V3.
    //假定要访问点1.
    for(const auto &ele:graph[1])//对于全部属于graph[1]这个容器的元素
    std::cout<

第二种(使用map,set):

方法太多,不再举例了。

然而我们这样存图是不够的,对于无向图而言,可能存在一条边需要知道自己的反向边的位置。例如欧拉回路,例如网络流都是需要的。

第二种方法由于std::map> graph;只是离散化后的邻接矩阵。对于这种存图方法,访问反向边则非常简单,例如我访问的是a->b这样一条边。那么只需要graph[b].count(a);就可以访问其反向边b->a。

然而对于第一种方法,我们没有办法解决反向边的互相访问题。

 

所以我们对于这种图需要存图修正。代码如下:

对于list容器可以直接存迭代器的,但是存图时也得考虑a是否等于b.forward_list存反向边的图就不好,因为用链表存图就是需要存完图后插入删除,假定一个元素前面的元素被删除了,那么根本无法访问反向边!!!!

感觉存图没问题了?NO!!!!还有一种图更奇葩,那就是对于每个点中的边得排序又得知道反向边的那种图。USACO上有个题目叫做骑马修栅栏,那个题要求字典序输出。数据量很小,以至于可以直接矩阵存图,但是我们考虑如何数据量大,这种方法就不行了。如果用第二种方法(std::map>)存图,绝对可以,但是相对常数较大。如果我们考虑顺序容器去存储则比较快一些。

方法就是先用边集表存图,然后每条边a,b得优先以std::min(a,b)为第一关键字再按std::max(a,b)为第二关键字排序,再按照修正后的存图方法存图即可。具体代码见nocow上骑马修栅栏那题lgeecn发的题解和代码。

如果使用list存图可以先存图再用list.sort()函数进行排序,不过似乎效率会差一些,毕竟相对于vector,list常数太大了,达到6倍以上。

存图真心不简单,因为真正用的时候你可能会遇到各种问题,但是你可以加以思考,进行容器搭配使用,即可解决。

#include
#include
#include
#include
#include
#include
intmain()
{
std::map>graph;
graph[0].insert(1);//V0->V1.
graph[1].insert(4);//V1->V4.
graph[1].insert(0);//V1->V0.
graph[2].insert(1);//V2->V1.
graph[2].insert(3);//V2->V3.
graph[3].insert(0);//V3->V0.
graph[4].insert(3);//V4->V3.
//假定要访问点1.
for(constauto&ele:graph[1])//对于全部属于graph[1]这个容器的元素
std::cout<

 

#include
#include
#include
#include
intmain()
{
std::vector>>graph(5);//每条边的第二个元素不能是迭代器!!会失效!!!!必须是下标!!!
//比如有一条a-b的边,我们得让它实现互访。我们这里假定a=2,b=4;
std::size_ta(2),b(4);
graph[a].push_back(std::make_pair(b,graph[b].size()+(a==b)));//Va->Vb.需要判定a是否等于b.
graph[b].push_back(std::make_pair(a,graph[a].size()-1));//Vb->Va,这个不需要判定a是否等于b.
//访问反向边的方法.
for(constauto&ele:graph[a])//访问点a
graph[ele.first][ele.second];//这就是边ele的反向边了
return0;
}

 

你可能感兴趣的:(邻接表(vector e[100]; e[x].push_back( (node){y,z} ); node(int a,int b):y(a),z(b){};))