树/图的存储方式

 

GeneralLiu

 

1 邻接矩阵

 

  bool/int  map[MAXN][MAXN];

  map[i][j]表示 i 到 j   是否连通 / 权值是多少

  遍历

    for()

      for()

        遍历整个数组

 

2 链式前向星

 

一种把节点 u 所连的边集合 {E} “串成一条 “链” ” 的表示方法

  int head[MAXN];  // head[u] 表示 与 u 相连通的 “链” 的 “头”(链的起点)边的 编号;

  struct Edge{

    int to;  // edge[i].to 表示 第i条有向边 到达的点 v(起始点为u,无向边存两遍就是了)

    int next;  // edge[i].next 表示 第i条有向边 所在链的 下一条 边的 编号 ;

    int dis; //edge[i].dis 表示 第i条有向边 的 权值 ;

  }edge[MAXN*2];//*2因为无向图要存两遍

 

遍历 与 u 相连的所有的 点 或 边  

  for(int i=head[u]; // i 初始化为 链头 边 的 编号

      i;  //  i为 0 时表示遍历到了 这条链的 链尾

      i=edge[i].next;)  // i 不断“指向”(更新为) 链中的 下一条边的 编号

    i 为 u 联通的边 的 编号,edge[i] 为权值,

    edge[i].to 为 u 联通的点 的 编号;

 

3 vector (不知道叫啥名)

 

可以理解为 邻接矩阵的优化

  vector<int>vec[MAXN] // 只存到达的节点

  vector<pair<int,int> >vec[MAXN]  //  vec[u][i].first 为到达的节点编号, vec[u][i].second 为此边的权值;

 

插入 u 与 v 相连

    vec[u].push_back(v),

    vec[v].push_back(u);

   若有权值 // make_pair(a,b) 可以 。。。额。 自己体会吧

    vec[u].push_back(make_pair(v,dis)),

    vec[v].push_back(make_pair(u,dis));

 

遍历

    for(int i=vec[u][0];

        i<vec[u].size();

        i++;)

 

 

以 洛谷 P2420 让我们异或吧 为例题

用 vector 和 链式前向星 分别 存储

对比二者差别

这道题会不会的吧,其实只是对比效率罢了

vector 代码短 好写 可读性强

#include<bits/stdc++.h>
using namespace std;
#define N 100005
int tree[N],n,m;
bool vis[N];
vector<pair<int,int> >vec[N];
void dfs(int k){
    vis[k]=1;
    int v;
    for(int i=0;i<vec[k].size();i++){
        v=vec[k][i].first;
        if(!vis[v]){
            tree[v]=vec[k][i].second ^ tree[k];
            dfs(v);
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int x,y,z,i=1;i<n;i++){
        scanf("%d%d%d",&x,&y,&z);
        vec[x].push_back(make_pair(y,z));
        vec[y].push_back(make_pair(x,z));
    }
    dfs(1);
    scanf("%d",&m);
    for(int x,y,i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        printf("%d\n",tree[x]^tree[y]);
    }
    return 0;
}
View Code

链式前向星 时间快 其实理解了 也是很好写 可读性也挺强

#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define E 200005
int cnt,dis[E],tree[N],n,m,head[N],to[E],next[E];
bool vis[N];
void dfs(int k){
    vis[k]=1;
    int v;
    for(int i=head[k];i;i=next[i]){
        v=to[i];
        if(!vis[v]){
            tree[v]=dis[i] ^ tree[k];
            dfs(v);
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int x,y,z,i=1;i<n;i++){
        scanf("%d%d%d",&x,&y,&z);
        next[++cnt]=head[x];
        to[cnt]=y;
        head[x]=cnt;
        dis[cnt]=z;
        next[++cnt]=head[y];
        to[cnt]=x;
        head[y]=cnt;
        dis[cnt]=z;
    }
    dfs(1);
    scanf("%d",&m);
    for(int x,y,i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        printf("%d\n",tree[x]^tree[y]);
    }
    return 0;
}
View Code

 

posted @ 2017-05-04 16:55  GeneralLiu  阅读(1794)  评论(2编辑  收藏  举报