《算法导论》笔记 第22章 总结与思考

来源:互联网 发布:高考后知哥哥去世 编辑:程序博客网 时间:2024/05/18 00:23

【总结】




【思考】


22-1 通过广度优先搜索对边进行分类



22-2 挂接点、桥以及双连通分支

a) G_π的根是G的挂接点,当且仅当在G_π中该根顶点至少有两个子女。


b) 设v是G_π中的某一非根顶点,证明v是G的挂接点当且仅当v有一个子顶点s,使得不存在从s或s的任何后裔顶点指向v的某个真祖先顶点的反向边。


c) 设low[v]=min(d[v],d[w]),d[w]:对v的后裔u,(u,w)是反向边

试说明对所有顶点v∈V,如何在O(E)时间内计算出low[v]。


----

资料:https://www.byvoid.com/blog/biconnect

----


const int maxn=1111;  const int maxm=5111;  int n,m;    struct EDGENODE{      int to;      int w;      bool cut;      int next;  };  struct SEDGE{      int u;      int v;      SEDGE(int uu=0,int vv=0){u=uu;v=vv;}  };  struct BCC_GRAPH{      int head[maxn];      EDGENODE edges[maxm];      int edge;      void init()      {          clr(head,-1);          edge=0;      }      void addedge(int u,int v,int c=0)      {          edges[edge].cut=0,edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;      }      //BCC_Tarjan      int dfn[maxn],low[maxn],bccno[maxn],dfs_clock,bcc_cnt;      bool iscut[maxn];      vector<int>bcc[maxn];      stack<SEDGE>stk;      int dfs(int u,int fa)      {          int lowu=dfn[u]=++dfs_clock;          int child=0;          for (int i=head[u];i!=-1;i=edges[i].next)          {              int v=edges[i].to;              if (v==fa) continue;              SEDGE e=SEDGE(u,v);              if (!dfn[v])              {                  stk.push(e);                  child++;                  int lowv=dfs(v,u);                  lowu=min(lowu,lowv);                  if (dfn[u]<=lowv) //cut 割点                  {                      iscut[u]=true;                      //done 点双连通                      bcc_cnt++;                      bcc[bcc_cnt].clear();                      SEDGE x;                      do{                          x=stk.top();                          stk.pop();                          if (bccno[x.u]!=bcc_cnt)                          {                              bcc[bcc_cnt].push_back(x.u);                              bccno[x.u]=bcc_cnt;                          }                          if (bccno[x.v]!=bcc_cnt)                          {                              bcc[bcc_cnt].push_back(x.v);                              bccno[x.v]=bcc_cnt;                          }                      }while (x.u!=u||x.v!=v);                      //over                  }                  if (dfn[u]<lowv)  //cut 桥                  {                      edges[i].cut=true;                      edges[i^1].cut=true;                  }              }              else if (dfn[v]<dfn[u])              {                  stk.push(e);//done                  lowu=min(lowu,dfn[v]);              }          }          if (fa<0&&child==1) iscut[u]=0;          low[u]=lowu;          return lowu;      }      void find_bcc(int n)      {          while (!stk.empty()) stk.pop();          clr(dfn,0);          clr(iscut,0);          clr(bccno,0);          dfs_clock=bcc_cnt=0;          REP_1(i,n)          {              if (!dfn[i]) dfs(i,-1);          }      }      //another      int block[maxn];      int vis[maxn];      int b_num;      void b_dfs(int u)      {          vis[u]=true;          block[u]=b_num;          for (int i=head[u];i!=-1;i=edges[i].next)          {              if (edges[i].cut) continue;              int v=edges[i].to;              if (!vis[v]) b_dfs(v);          }      }      void find_block(int n)      {          //find_block 边双连通          clr(block,0);          clr(vis,0);          b_num=0;          REP_1(i,n)          {              if (!vis[i])              {                  b_num++;                  b_dfs(i);              }          }      }  }solver;  


----


22-3 欧拉回路

使用深度优先搜索,如果某条边被搜索到,则标记这条边为已选择,并且即使回溯也不能将当前边的状态改回未选择,每次回溯时,记录回溯路径。深度优先搜索结束后,记录的回溯路径就是欧拉回路。

----

void dfs(int u)  {      for (int i=1;i<=n;i++)      {          if (a[u][i])          {              a[u][i]=false;              a[i][u]=false;              dfs(i);              ans[++cnt]=i;          }      }  }  


----


22-4 可达性




0 0
原创粉丝点击