• POJ1639 Picnic Planning (K度限制最小生成树)


    题目链接:
    POJ1639 Picnic Planning
    洛谷 UVA1537 Picnic Planning
    题目大意:
    给出一个 (N) 个点的无向图,在满足树上节点1的度数 (leq k) 的条件下,求其最小生成树。
    (1leq Nleq 20)
    思路:
    题目即求K度限制最小生成树,考虑这样一个算法:

    1. 首先划分删除节点1后产生的连通块,并在连通块中求各自的最小生成树。
    2. 找到块中距离节点1最近的点,并将其与节点1之间的边选上。

    设连通块的个数为 (d) ,则我们还剩 (k-d) 的度数没有用,这时尝试将 (ans) 优化,将步骤3执行 (k-d) 次:

    1. 扫描节点1的剩下未加入出边,记边权为 (w) ,查找边所连接的点 (x) 在树上到节点1的路径中边权 (w') 最大的边 (e') ,找到使得 (w'-w) 最大的边 (e) ,若 (w'-wleq0) 则结束,否则 (ans-=w'-w) ,同时将 (e) 加入,并将 (e') 删除。

    最后得到的就是所求答案,直接朴素维护的时间复杂度为 (O(n^3)) , (Link-Cut-Tree) 维护时间复杂度 (O(nlog^2n)) ,所以可以把数据加强到 (1leq Nleq 200000) (然后就变成了毒瘤题)。

    细节:
    细节就是有很多细节,但是比较好写。

    Code:

    #include<iostream>
    #include<algorithm>
    #include<map>
    #include<cstring>
    #define N 23
    #define E 440
    #define Inf 0x3f3f3f3f
    using namespace std;
    struct edge{
        int u,v,len;
        bool tf;
    }e[E],maxx;
    map<string,int> dict;
    int cnt,n,fa[N];
    int conn[N][N],ans;
    bool tree[N][N];
    int vis[N];
    int find(int x){
        if(fa[x]==x)return x;
        return fa[x]=find(fa[x]);
    }
    bool cmp(edge a,edge b){
        return a.len<b.len;
    }
    void dfs1(int x){
        vis[x]=1;
        for(int i=2;i<=n;i++)
            if(conn[x][i]){
                if(x<=i){
                    e[++cnt].u=x, e[cnt].v=i;
                    e[cnt].len=conn[x][i];
                }
                if(!vis[i])dfs1(i);
            }
    }
    int dfs2(int x,int fa,int goal){
        if(x==goal)return 0;
        for(int i=1;i<=n;i++)
            if(tree[x][i]&&i!=fa){
                int temp=dfs2(i,x,goal);
                if(~temp){
                    if(conn[x][i]>temp)maxx.u=x,maxx.v=i;
                    return max(conn[x][i],temp);
                }
            }
        return -1;
    }
    bool Max(int &a,int b){
        if(a>=b)return false;
        a=b; return true;
    }
    bool Min(int & a,int b){
        if(a<=b)return false;
        a=b; return true;
    }
    int kruskal(){
        int ret=0;
        sort(e,e+cnt+1,cmp);
        for(int i=0;i<=cnt;i++){
            int x=find(e[i].u),y=find(e[i].v);
            if(x==y)continue;
            tree[e[i].u][e[i].v]=tree[e[i].v][e[i].u]=true;
            ret+=e[i].len;
            fa[x]=y;
        }
        return ret;
    }
    int main(){
        int m,k;
        int len,u,v;
        string a,b;
        cin>>m;
        n=dict["Park"]=1;
        for(int i=0;i<m;i++){
            cin>>a>>b>>len;
            if(!dict[a])dict[a]=++n;
            if(!dict[b])dict[b]=++n;
            u=dict[a],v=dict[b];
            conn[u][v]=conn[v][u]=len;
        }
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)fa[i]=i;
        int deg=0;
        vis[1]=2;
        for(int i=1;i<=n;i++){
            if(!conn[1][i]||vis[i])continue;
            cnt=-1;
            dfs1(i);
            ans+=kruskal();
            int minn=Inf,node;
            for(int i=1;i<=n;i++)
                if(vis[i]==1){
                    vis[i]=2;
                    if(conn[1][i]&&Min(minn,conn[1][i]))node=i;
                }
            tree[1][node]=tree[node][1]=true;
            ans+=minn;
            deg++;
        }
        cin>>k;
        for(int i=0;i<k-deg;i++){
            int delta=0,node;
            edge del;
            for(int i=1;i<=n;i++){
                if(!conn[1][i])continue;
                if(Max(delta,dfs2(1,-1,i)-conn[1][i])) node=i,del=maxx;
            }
            if(delta<=0)break;
            ans-=delta;
            tree[del.u][del.v]=tree[del.v][del.u]=false;
            tree[1][node]=tree[node][1]=true;
        }
        cout<<"Total miles driven: "<<ans;
        return 0;
    }
    

    洛谷上的AC代码在这(题目变成了多组数据):https://www.luogu.com.cn/paste/wc62iorg

  • 相关阅读:
    8.11 hdu 多校第五场补题
    8.10 trie树模板
    8.6 edu25 ,577#div2 CF补题(二分 ,dp 与 贪心
    8.4 POJ 3237 (树链剖分+线段树
    8.4 poj 2763 Housewife Wind (树链剖分边权处理
    8.4 树链剖分
    8.3 树链剖分
    2019 hdu 第四场补题 (2
    2019 hdu 第四场补题 (1 ,签到题
    51NOD 1137 矩阵乘法
  • 原文地址:https://www.cnblogs.com/Neal-lee/p/14206009.html
Copyright © 2020-2023  润新知