• BZOJ 4349: 最小树形图


    Description

    (n)个节点,每个节点有一个攻击代价和需要攻击的次数。

    有(k)个关系,攻击(x)后,(y)的攻击代价变成(z)。

    Solution

    朱刘算法。

    这个好像就是求什么最小树形图的东东...

    最小树形图跟最小生成树差不多,不过最小生成树是无向图,最小树形图是有向图,让一个节点和其他节点联通的最小代价。

    这个建模也非常容易,只需要确定第一次的攻击即可,之后的一定都以最小代价攻击。

    朱刘算法也很简单,步骤就是

    找到每个节点的最小入边。

    统计答案。

    找环,缩环,把边权设成原边权-最小入边边权。

    Code

    /**************************************************************
        Problem: 2260
        User: BeiYu
        Language: C++
        Result: Accepted
        Time:8 ms
        Memory:1340 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    using namespace std;
     
    inline int in(int x=0,char ch=getchar()) { while(ch>'9' || ch<'0') ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; }
     
    const int N = 55;
    const int M = N*N+50;
     
    struct Edge { int fr,to;double v; };
    Edge edge[M];
     
    int n,m,rt;
    int b[N];
    double mic[N];
    double miv[N];
    int pre[N],vis[N],id[N];
     
    void AddEdge(int fr,int to,double v) { edge[++m]=(Edge){ fr,to,v }; }
     
    double Solve(int n) {
        double res=0;
        for(int cnt,tmp;;) {
            for(int i=1;i<=n;i++) miv[i]=1e9,pre[i]=0;
            for(int i=1;i<=m;i++) {
                Edge &e=edge[i];
                if(e.v<miv[e.to]) miv[e.to]=e.v,pre[e.to]=e.fr;
            }
            for(int i=1;i<=n;i++) if(pre[i]) res+=miv[i];
            memset(vis,0,sizeof(vis));
            memset(id,0,sizeof(id));
            vis[0]=tmp=1,cnt=0;
            for(int i=1;i<=n;i++) if(!vis[i]) {
                ++tmp;int u=i;
                for(;!vis[u];u=pre[u]) vis[u]=tmp;
                if(vis[u]==tmp) {
                    ++cnt;
                    for(;!id[u];u=pre[u]) id[u]=cnt;
                }
            }
            if(!cnt) break;
            for(int i=1;i<=n;i++) if(!id[i]) id[i]=++cnt;
            int mm=m;m=0;
            for(int i=1;i<=mm;i++) {
                Edge &e=edge[i];
                if(id[e.fr]!=id[e.to]) AddEdge(id[e.fr],id[e.to],e.v-miv[e.to]);
            }
            n=cnt;
        }return res;
    }
     
    int main() {
        n=in(),rt=n+1;
        for(int i=1;i<=n;i++) {
            double x;scanf("%lf",&x);
            mic[i]=x;
            b[i]=in();
            if(b[i]) AddEdge(rt,i,x);
        }
        for(int k=in();k--;) {
            int x=in(),y=in();
            double z;scanf("%lf",&z);
            if(b[x] && b[y]) {
                AddEdge(x,y,z);
                mic[y]=min(mic[y],z);
            }
        }
        double ans=Solve(n+1);
    //  cout<<ans<<endl;
    //  for(int i=1;i<=n;i++) cout<<mic[i]<<" ";cout<<endl;
        for(int i=1;i<=n;i++) if(b[i]) ans+=(b[i]-1)*mic[i];
        printf("%.2lf
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    Please provide compiled classes of your project with sonar.java.binaries property
    全链路压测
    零宽度短网址生成器
    http://www.easytest.xyz/login_action/
    进程间的五种通信方式介绍
    InteiiJ IDEA中如何制定制定哪一个配置文件
    常见的各种排序算法汇总
    编程面试之前你应该知晓的八大数据结构
    rest-assured-doc接口自动化测试,数据驱动测试平台
    Jenkins 邮件配置 || Jenkins 发送邮件失败,提示:Error sending to the following VALID addresses
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6598524.html
Copyright © 2020-2023  润新知