zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      题目传送门

    道路费用

    格式难调,题面就不放了。


      分析:

      这是一道要细(yan)心(jing)的生成树的好(gui)题。

      首先我们看到$k$的范围非常小,那么我们就可以直接$2^k$枚举每一条加边是否选择。然后我们再按权值大小依次加原边并且更新可以影响的加边的权值上限,再树形DP求解。但是这样复杂度是$O(2^k+NMlog M)$,需要考虑优化。

      我们能发现,不管加边选不选,有一些边都一定会加入到生成树中,那么我们就把这些边提前连接,然后把产生出的联通块缩点,然后就能形成一个$k+1$个点的新图和$k$条加边和$k$条原边,再用上面的操作就行了。现在的复杂度是$2^k+Mlog M$,可以接受了。

      细节贼多,贼难调。。。

      Code:(代码贼丑。。。)

    //It is made by HolseLee on 3rd Oct 2018
    //Luogu.org P3639 
    #include<bits/stdc++.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    
    typedef long long ll;
    const int N=1e5+7, M=3e5+7;
    int n,m,K,sta,top,ag[25],fa[N],fa2[N];
    int mn[N],dep[N],head[N],p[N],cnte;
    ll val[N],sum[N],ans;
    struct Edge {
        int to,nxt;
        Edge() {}
        Edge(const int _x,const int _y): to(_x),nxt(_y) {}
    }edge[M];
    struct Node {
        int u,v,w;
        bool operator < (const Node x) const {
            return w < x.w;
        }
    }e[M],ne[25],q[M];
    bool mark[M];
    
    inline int read()
    {
        char ch=getchar(); int num=0; bool flag=false;
        while( ch<'0' || ch>'9' ) {
            if( ch=='-' ) flag=true; ch=getchar();
        }
        while( ch>='0' && ch<='9' ) {
            num=num*10+ch-'0'; ch=getchar(); 
        }
        return flag ? -num : num; 
    }
    
    int find(int x) { return fa[x]==x ? x : fa[x]=find(fa[x]); }
    int find2(int x) { return fa2[x]==x ? x : fa2[x]=find2(fa2[x]); }  
    
    inline void add(int x,int y)
    {
        edge[++cnte]=Edge(y,head[x]); head[x]=cnte;
        edge[++cnte]=Edge(x,head[y]); head[y]=cnte;
    }
    
    void get(int x) 
    {
        sum[x]=val[x];
        for(int i=head[x]; i; i=edge[i].nxt) {
            if( edge[i].to==fa2[x] ) continue;
            dep[edge[i].to]=dep[x]+1;
            fa2[edge[i].to]=x; 
            get(edge[i].to);
            sum[x]+=sum[edge[i].to];
        }
    }
    
    inline void work()
    {
        cnte=0;
        for(int i=1; i<=K+1; ++i) {
            int hl=ag[i]; head[hl]=fa2[hl]=0;
            fa[hl]=hl;mn[hl]=inf;
        }
        int u,v,fu,fv;
        for(int i=1; i<=K; ++i) 
        if( mark[i] ) {
            u=find(ne[i].u), v=find(ne[i].v); if( u==v ) return;
            fa[u]=v; add(ne[i].u,ne[i].v);
        }
        for(int i=1; i<=K; ++i) {
            u=find(q[i].u), v=find(q[i].v);
            if( u!=v ) fa[u]=v, add(q[i].u, q[i].v);
        }
        get(sta);
        for(int i=1; i<=K; ++i) {
            u=q[i].u, v=q[i].v;
            if( dep[u]>dep[v] ) swap(u,v);
            while( dep[v]>dep[u] ) mn[v]=min(mn[v],q[i].w), v=fa2[v];
            while( u!=v ) {
                mn[v]=min(mn[v],q[i].w); mn[u]=min(mn[u],q[i].w);
                u=fa2[u], v=fa2[v];
            }
        }
        ll now=0;
        for(int i=1; i<=K; ++i) 
        if( mark[i] ) {
            u=ne[i].u, v=ne[i].v; 
            if( dep[u]>dep[v] ) swap(u,v);
            now+=mn[v]*sum[v];
        }
        if( ans<now ) ans=now;
    }
    
    void dfs(int x)
    {
        if( x>K ) { work(); return; }
        mark[x]=0; dfs(x+1); mark[x]=1; dfs(x+1);
    }
    
    int main()
    {
        n=read(), m=read(), K=read();
        for(int i=1; i<=m; ++i) {
            e[i].u=read(), e[i].v=read(), e[i].w=read();
        }
        sort(e+1,e+m+1);
        for(int i=1; i<=K; ++i) {
            ne[i].u=read(), ne[i].v=read();
        }
        for(int i=1; i<=n; ++i) p[i]=read(), fa[i]=fa2[i]=i;
        for(int i=1; i<=K; ++i) fa[find(ne[i].u)]=find(ne[i].v);
        int u,v,fu,fv;
        for(int i=1; i<=m; ++i) {
            u=e[i].u, v=e[i].v;
            if( (fu=find(u))!=(fv=find(v)) ) {
                fa[fu]=fa[fv]; fa2[find2(u)]=fa2[find2(v)];
            }
        }
        sta=find2(1);
        for(int i=1; i<=n; ++i) {
            val[fu=find2(i)]+=p[i]; if( fu==i ) ag[++ag[0]]=i;
        }
        for(int i=1; i<=K; ++i) {
            ne[i].u=find2(ne[i].u); ne[i].v=find2(ne[i].v);
        }
        for(int i=1; i<=m; ++i) {
            e[i].u=find2(e[i].u); e[i].v=find2(e[i].v);
        }
        for(int i=1; i<=m; ++i) {
            u=find2(e[i].u), v=find2(e[i].v);
            if( u!=v ) q[++top]=e[i], fa2[u]=v;
        }
        dfs(1); printf("%lld
    ",ans);
        return 0;
    } 
  • 相关阅读:
    编码问题:python写入文件
    [ExtJS5学习笔记]第三十二节 sencha extjs 5与struts2的ajax交互配置
    PS 滤镜——Skewing
    [struts2学习笔记] 第六节 struts2依赖的jar包还有Could not find action or result 错误解决
    [linux RedHat]windows下使用putty远程连接linux 下载JDK和tomcat
    一个有趣的花环图案生成函数
    【翻译】针对多种设备定制Ext JS 5应用程序
    【翻译】Ext JS最新技巧——2015-1-2
    [ExtJS5学习笔记]第三十一节 sencha extjs 5使用cmd生成的工程部署到tomcat服务器
    PhotoShop 图像处理 算法 汇总
  • 原文地址:https://www.cnblogs.com/cytus/p/9740986.html
Copyright © 2011-2022 走看看