zoukankan      html  css  js  c++  java
  • [ACM]最小度限制生成树

    最小度限制生成树是指某一个节点的度限制为k的最小生成树。具体的做法去看论文或者黑书吧,这里不详细讲了。

    理解最小度限制生成树的解法,最主要的就是看懂如何由m度生成树求m+1度生成树,另外要理解无解的情况。

    今天终于把模板整理出来了,prim那里用了优先队列优化,添加删除边破环那里用的是动态规划。试了试PKU1639这道题,结果正确,但是由于数据水,不知道效率如何。

    贴出模板:

      1 #define maxn 505
      2 struct str
      3 {
      4     int v,c,n;
      5 }edge[maxn<<1];//邻接表
      6 int head[maxn],cnt;
      7 void init()
      8 {
      9     memset(head,-1,sizeof(head));
     10     cnt=0;
     11 }
     12 void addEdge(int u,int v,int c)
     13 {
     14     edge[cnt].v=v;
     15     edge[cnt].c=c;
     16     edge[cnt].n=head[u];
     17     head[u]=cnt++;
     18     edge[cnt].v=u;
     19     edge[cnt].c=c;
     20     edge[cnt].n=head[v];
     21     head[v]=cnt++;
     22 }
     23 int dis[maxn],best[maxn],index[maxn];
     24 //dis是prim里到某节点的最短距离,best具体含义看论文,index是best对应的边号
     25 int incom[maxn],com;//记录节点在哪个联通分量里
     26 bool vis[maxn],intree[maxn<<1];
     27 struct node
     28 {
     29     int u,c,e;//u是邻接表里对应的那个v,c是边权,e是边号
     30     node(){}
     31     node(int _u,int _c,int _e):u(_u),c(_c),e(_e){}
     32     bool operator <(const node a)const{return a.c<c;}
     33 };//优先队列数据结构
     34 priority_queue<node>q;
     35 int prim(int n,int s)
     36 {
     37     for(int i=0;i<=n;i++)dis[i]=inf;
     38     memset(vis,0,sizeof(vis));vis[s]=true;
     39     memset(intree,0,sizeof(intree));//判断边是否在生成树中
     40     int val=0;com=0;
     41     for(int i=1;i<=n;i++)if(!vis[i])//求各个连通分量的最小生成树
     42     {
     43         dis[i]=0;++com;q.push(node(i,0,-1));
     44         while(!q.empty())
     45         {
     46             int u=q.top().u,e=q.top().e,c=q.top().c;q.pop();
     47             if(vis[u])continue;
     48             val+=c;incom[u]=com;
     49             vis[u]=intree[e]=intree[e^1]=true;
     50             for(int j=head[u];j!=-1;j=edge[j].n)
     51             {
     52                 int v=edge[j].v,c=edge[j].c;
     53                 if(vis[v])continue;
     54                 if(dis[v]>c)dis[v]=c,q.push(node(v,c,j));
     55             }
     56         }
     57     }
     58     memset(vis,0,sizeof(vis));//vis数组复用,判断某节点所在的连通分量是否已经连接
     59     for(int i=head[s];i!=-1;i=edge[i].n)
     60     {
     61         int v=edge[i].v,c=edge[i].c;
     62         q.push(node(v,c,i));
     63     }
     64     while(!q.empty())//把各个分量连起来,这样就求出m度最小生成树
     65     {
     66         int v=q.top().u,c=q.top().c,e=q.top().e;
     67         q.pop();
     68         if(!vis[incom[v]])
     69             val+=c,intree[e]=intree[e^1]=vis[incom[v]]=true;
     70     }
     71     return val;
     72 }
     73 void dfs(int u,int fa,int n,int s)//更新best
     74 {
     75     for(int i=head[u];i!=-1;i=edge[i].n)if(intree[i])
     76     {
     77         int v=edge[i].v,c=edge[i].c;
     78         if(v==fa)continue;
     79         if(u==s)best[v]=-inf,index[v]=i;
     80         else
     81         {
     82             if(best[u]>c)best[v]=best[u],index[v]=index[u];
     83             else best[v]=c,index[v]=i;
     84         }
     85         dfs(v,u,n,s);
     86     }
     87 }
     88 //int mval;
     89 int klimit(int n,int s,int k)//求k度最小生成树,n是节点个数,s是度被限制的节点,k为限制的度数
     90 {
     91     int val=prim(n,s);
     92     //mval=val;
     93     if(k<com)return inf;//如果k小于连通分量个数,则无解
     94     best[s]=-inf;dfs(s,-1,n,s);
     95     for(int i=com+1;i<=k;i++)
     96     {
     97         int mn=inf,ed=-1;
     98         for(int j=head[s];j!=-1;j=edge[j].n)if(!intree[j])
     99         {
    100             int v=edge[j].v,c=edge[j].c;
    101             if(mn>c-best[v])mn=c-best[v],ed=j;
    102         }
    103         if(ed==-1)return inf;//无法再使度扩大则也是无解的
    104         int v=edge[ed].v,dx=index[v];
    105         val+=mn;
    106         //mval=min(val,mval);
    107         intree[ed]=intree[ed^1]=true;
    108         intree[dx]=intree[dx^1]=false;
    109         best[v]=-inf,dfs(v,s,n,s);
    110     }
    111     return val;
    112 }

    如果是求某节点正好为k度则就是上面的模板,如果节点的度不大于k则将上面mval的三条注释取消掉,最后结果就是mval。

  • 相关阅读:
    django中的objects.get和objects.filter方法的区别
    Django之CSRF
    Django之include本质
    django中的FBV和CBV
    HTTP协议【详解】——经典面试题
    Python中的魔法函数__repr__和__str__的实质性区别
    浅谈CSS中的百分比
    深入理解定时器系列第一篇——理解setTimeout和setInterval
    Javascript学习
    HTML中块级元素和行内元素的总结和区分。
  • 原文地址:https://www.cnblogs.com/mcflurry/p/2964890.html
Copyright © 2011-2022 走看看