• BZOJ4349 最小树形图


    据说是一道重题 可以见[JSOI2008]小店购物

    同样是最小树形图 可以注意到每个点只要都被打了一次那么接下来都可以使用最小的代价来攻打

    那么我们把第一次进行的攻打跑最小树形图即可 注意要建虚点作为起始状态

    【最开始想错了 以为必须全打掉才可以用后来的新代价 WA飞以后看题解才明白qaq

    //Love and Freedom.
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define inf 1e20
    #define ll long long
    #define N 1100
    #define M 100100
    #define db double
    using namespace std;
    
    struct edge{int u,v; db c;}e[M];
    int pre[N],id[N],vis[N];
    int n,m;db mn[N];
    db zlal(int rt)
    {
        db res = 0.0;
        while(1)
        {
            for(int i=1;i<=n;i++)    mn[i] = inf;
            for(int i=1;i<=m;i++)
                if(e[i].u != e[i].v && mn[e[i].v]>e[i].c)
                {
                    mn[e[i].v] = e[i].c; pre[e[i].v] = e[i].u;
                }
            for(int i=1;i<=n;i++)    if(i!=rt && mn[i]==inf)    return 0;
            int tn = 0,u,v;
            memset(id,0,sizeof(id)); memset(vis,0,sizeof(vis));
            mn[rt] = 0;
            for(int i=1;i<=n;i++)
            {
                res += mn[i]; v=i;
                while(v!=rt && !id[v] && vis[v]!=i)
                    vis[v] = i, v = pre[v];
                if(v!=rt && !id[v])
                {
                    ++tn;
                    for(u=pre[v];u!=v;u=pre[u])
                        id[u] = tn;
                    id[v] = tn;
                }
            }
            if(!tn)    break;
            for(int i=1;i<=n;i++)    if(!id[i])
                id[i] = ++tn;
            for(int i=1;i<=m;i++)
            {
                v = e[i].v;
                e[i].u = id[e[i].u];
                e[i].v = id[e[i].v];
                if(e[i].u != e[i].v)
                    e[i].c -= mn[v];
            }
            n = tn; rt = id[rt];
        }
        return res;
    }
    db a[N],cc[N]; int b[N],cnt;
    int main()
    {
        //int r;    scanf("%d%d%d",&n,&m,&r);
        //for(int i=1;i<=m;i++)    scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);
        scanf("%d",&n); n++; db ans = 0.0;
        for(int i=1;i<n;i++)
        {
            scanf("%lf%d",&a[i],&b[i]);
            if(b[i]<=0)    continue;// ans+=(b[i]-1)*a[i];
            e[++cnt].u = n, e[cnt].v=i ,cc[i]=e[cnt].c=a[i];
        }
        int k,x,y;db c; scanf("%d",&k);
        for(int i=1;i<=k;i++)
        {
            scanf("%d%d%lf",&x,&y,&c);
            e[++cnt].u=x; e[cnt].v=y; e[cnt].c=c; cc[y]=min(cc[y],c);
        } m = cnt;
        for(int i=1;i<n;i++)    ans+=(b[i]-1)*cc[i];
        printf("%.2lf
    ",zlal(n) +ans);
        return 0;
    }
    /**
    3 
    10.00 1
    1.80 1 
    2.50 2
    2
    1 3 2.00
    3 2 1.50
    */
    View Code
  • 相关阅读:
    神经网络学习之----单层感知器
    神经网络学习之----神经网络发展史
    神经网络学习之----神经网络概述
    C语言几种常见的字符串输入
    基于单链表实现集合的交集、并集、差集的运算
    关于单链表的一些基本操作
    输入20个整数存放到一个单向链表中,并顺序逆序输出
    《你的灯亮着吗》阅读笔记
    场景调研
    站立会议总结09
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10366717.html
Copyright © 2020-2023  润新知