樹/圖的存儲方式


 

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM