图论小结(6.7)

   二分图的几个概念及代码,最小生成树的复杂度,寻找欧拉路径的算法及代码


  1.几个原来不是很清楚的概念:


   二分图的最大独立点集:  在所有顶点中选一些点,使得这个点集内两两之间无连线,那么这个点集就叫做独立点集,而顶点数最多的那个集合就是最大独立集。


   最小点覆盖:  选取一部分点,使得这些点能够覆盖图中所有的边。满足所选点的个数最小的点即为最小点覆盖。

  

    定理:二分图的最大匹配=最小点覆盖

    推论:最大独立集=节点数 - 最大匹配。

    模板:(顶点编号从1开始)

bool dfs(int u)
{
     for(int i=0;i<G[u].size();i++){
          int v=G[u][i];
          if(!used[v]){
               used[v]=1;
               if(linked[v]==-1||dfs(linked[v])){
                    linked[v]=u;
                    return 1;
               }
          }
     }
     return 0;
}
int solve()
{
     memset(linked,-1,sizeof(linked));
     int u,res=0;
     for(u=1;u<=n;u++){
          memset(used,0,sizeof(used));
          if(dfs(u)) res++;
     }
     return res;
}

  2.关于最小生成树算法的复杂度:


    prim算法:时间复杂度O(n^2),空间复杂度O(n).

    Kruskal算法:时间复杂度O(mlogm) ,空间复杂度O(m).

    所以对于完全图的话,选用prim算法比较OK!


  3.关于欧拉路径的算法:

   1.朴素的求欧拉路径的算法:  时间复杂度比较高!!!

    关键代码:

  

void dfs(int v)
{
    for(int i=fa[v];i!=-1;i=e[i].next){
        int id=e[i].id,u=e[i].u;
        if(!used[id]){
            used[id]=1;
            dfs(u);
            ans[++h]=id;
        }
    }
}

  2.fleury算法: 比较高效的欧拉路径:  搜索效率比较高!!!

    关键代码:

  

void dfs(int u,int dx)
{
    for(int i=0;i<G[u].size();i++){
        int id=G[u][i].SD,v=G[u][i].FT;//id记录这条边的编号,v为这条边的要到达的另一个节点
        G[u][i] = G[u][G[u].size()-1];
        G[u].erase(G[u].end()-1);
        dfs(v,id);
        i--;
    }
    stk.push(dx);//如果要记录的是节点顺序,改为stk.push(u)即可!
}

  反正我开始是没看懂,后来手动模拟了一下,主要是要理解那个
  stk.push(dx);
  每次搜索完后,直接删除这个节点,删除的方式比较特别,先用最后一个数赋覆盖当前搜索的数,然后直接删除最 后一个数,这样就比较优雅的删除了最后一个数。然后呢,就是去理解这个最后的过程了,建议手动模拟,每次把当前的状态压入堆栈,来模拟一下,或者自己输出中间过程看看实现过程。


  最后再次贡献一个比较能理解的版本(代码量比较大!!),其实就是吧原来那个stk.push(dx)的过程弄的特别复杂了而已!

  关键代码:


void dfs(int x){
    int i;
    s.top++;
    s.node[s.top]=x;
    for(i=0;i<n;i++){
        if(Edge[i][x]>0){
            Edge[i][x]=0;
            Edge[x][i]=0;
            dfs(i);
            break;
        }
    }
}
void Fleury(int x){
    int i,b;
    s.top=0;s.node[s.top]=x;
    while(s.top>=0){
        b=0;
        for(i=0;i<n;i++){
            if(Edge[s.node[s.top]][i]>0){
                b=1;break;
            }
        }
        if(b==0){
            printf("%d ",s.node[s.top]+1);
            s.top--;
        }
        else{
            s.top--;
            dfs(s.node[s.top+1]);
        }
    }
    printf("\n");
}

 最后一点分析: 为什么朴素的寻找欧拉路径的算法会明显慢与fluery算法???

 仔细点看不难发现,朴素的寻找欧拉路径的算法,在递归寻找节点继续搜索时,会遍历所有与之相连的边,然后判断是否这条边时候已经被走过,但是fluery算法不同之处就在于它把已经搜索过的节点都删除掉了,下次再来遍历这个节点的时候循环次数会减1,从而达到了缩短搜索时间的目的!



转载注明出处,谢谢!


  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值