【BZOJ】4349: 最小树形图
题解
我们只考虑给每个点买一个,之后每个点就可以用最低价格买了
根据最小树形图的算法,就是不断给每个点入度的边找一条最小的
如果构成了树形图就退出,否则把形成了环的点缩成一个点,加上环的权值,然后把指向环中点的弧变成弧长减去环中指向该点的弧的长度
重标号让代码显得好难看啊QAQ
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 1000005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,num[55],Ncnt,id[55];
db g[55][55],f[55][55],ans,val[55],tmp,minv[55];
int h[55][55],sta[55],top,low[55],dfn[55],idx,instack[55],tot;
int que[55],qr;
void Tarjan(int u) {
    low[u] = dfn[u] = ++idx;
    sta[++top] = u;
    instack[u] = 1;
    for(int v = 1 ; v < Ncnt ; ++v) {
        if(h[u][v]) {
            if(!dfn[v]) {Tarjan(v);low[u] = min(low[u],low[v]);}
            else if(instack[v] == 1) {low[u] = min(low[u],dfn[v]);}
        }
    }
    if(low[u] >= dfn[u]) {
        ++tot;
        qr = 0;
        while(1) {
            int x = sta[top--];
            id[x] = tot;
            que[++qr] = x;
            instack[x] = 2;
            if(x == u) break;
        }
        if(qr == 1) {val[que[1]] = 0;}
        else {
            for(int i = 1 ; i <= qr ; ++i) ans += val[que[i]];
        }
    }
}
void shortest_arborescence() {
    while(1) {
        memset(h,0,sizeof(h));
        tmp = 0.0;
        for(int i = 1 ; i < Ncnt ; ++i) {
            int t = Ncnt;
            for(int j = 1 ; j < Ncnt ; ++j) {
                if(g[j][i] < g[t][i]) t = j;
            }
            h[t][i] = 1;
            val[i] = g[t][i];
            tmp += val[i];
        }
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(instack,0,sizeof(instack));
        tot = 0;idx = 0;top = 0;
        for(int i = 1 ; i < Ncnt ; ++i) {
            if(!dfn[i]) Tarjan(i);
        }
        id[Ncnt] = ++tot;
        if(tot == Ncnt) {
            ans += tmp;
            break;
        }
        for(int i = 1 ; i <= tot ; ++i) {
            for(int j = 1 ; j <= tot ; ++j) {
                f[i][j] = 1000000000.0;
            }
        }
        for(int i = 1 ; i <= Ncnt ; ++i) {
            for(int j = 1 ; j <= Ncnt ; ++j) {
                if(id[i] == id[j]) continue;
                if(g[i][j] < 1000000000)
                    f[id[i]][id[j]] = min(f[id[i]][id[j]],g[i][j] - val[j]);
            }
        }
        Ncnt = tot;
        memcpy(g,f,sizeof(f));
    }
    printf("%.2lf\n",ans);
}
void Solve() {
    read(N);
    for(int i = 1 ; i <= N + 1 ; ++i) {
        for(int j = 1 ; j <= N + 1 ; ++j) {
            g[i][j] = 1000000000.0;
        }
    }
    for(int i = 1 ; i <= N ; ++i) {
        scanf("%lf",&minv[i]);
        read(num[i]);
        g[N + 1][i] = minv[i];
        if(num[i]) id[i] = ++Ncnt;
    }
    id[N + 1] = ++Ncnt;
    int k,A,B;db c;
    read(k);
    for(int i = 1 ; i <= k ; ++i) {
        read(A);read(B);scanf("%lf",&c);
        g[A][B] = min(g[A][B],c);
        if(num[A]) minv[B] = min(minv[B],c);
    }
    for(int i = 1 ; i <= N ; ++i) {
        if(num[i]) ans += minv[i] * (num[i] - 1);
    }
    for(int i = 1 ; i <= Ncnt ; ++i) {
        for(int j = 1 ; j <= Ncnt ; ++j) {
            f[i][j] = 1000000000.0;
        }
    }
    for(int i = 1 ; i <= N + 1; ++i) {
        if(!id[i]) continue;
        for(int j = 1 ; j <= N + 1; ++j) {
            if(!id[j]) continue;
            f[id[i]][id[j]] = g[i][j];
        }
    }
    memcpy(g,f,sizeof(g));
    shortest_arborescence();
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}
												
											【BZOJ】4349: 最小树形图的更多相关文章
- 【刷题】BZOJ 4349 最小树形图
		
Description 小C现在正要攻打科学馆腹地------计算机第三机房.而信息组的同学们已经建好了一座座堡垒,准备迎战.小C作为一种高度智慧的可怕生物,早已对同学们的信息了如指掌. 攻打每一个人 ...
 - bzoj 4349 最小树形图——朱刘算法
		
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4349. 学习博客:http://www.cnblogs.com/xzxl/p/7243466 ...
 - bzoj2260: 商店购物 && 4349: 最小树形图
		
Description Grant是一个个体户老板,他经营的小店因为其丰富的优惠方案深受附近居民的青睐,生意红火.小店的优惠方案十分简单有趣.Grant规定:在一次消费过程中,如果您在本店购买了精制油 ...
 - bzoj2260: 商店购物&&4349: 最小树形图
		
最小树形图问题啊 最小树形图是撒哩,就是给你一个有向图,确定一个根,要你到达所有点,那棵最短路径树的总边权 做这个用的是朱(jv)刘(lao)算法. 首先假如有多个联通块就无解啦 对应每个点(除了根) ...
 - 【Bzoj2260】【Bzoj4349】商店购物 & 最小树形图
		
目录 List Bzoj 2260 商店购物 Description Input Output Sample Input Sample Output Bzoj 4349 最小树形图 Descripti ...
 - 【BZOJ 2753】 2753: [SCOI2012]滑雪与时间胶囊 (分层最小树形图,MST)
		
2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 2457 Solved: 859 Descriptio ...
 - BZOJ 2260 商店购物(最小树形图)
		
不会最小树形图的出门左转 其实如果确定每种商品第一件的购买顺序,那么剩下的商品肯定是以最优惠价格购买的. 如何确定各种商品第一件购买时的最小价值呢? 考虑如果购买了\(a_i\)这种商品,那么就能以\ ...
 - 【最小树形图(奇怪的kruskal)】【SCOI 2012】【bzoj 2753】滑雪与时间胶囊
		
2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec Memory Limit: 128 MB Submit: 1621 Solved: 570 Description ...
 - [JSOI2008]小店购物 & bzoj4349:最小树形图      最小树形图
		
---题面(洛谷)--- ---题面(bzoj)--- 其实是同一道题,,,样例都一模一样 题解: 一开始看想了好久,,,还想到了最短路和最小生成树,,然而写的时候才意识到最小生成树应该要用无向边 其 ...
 
随机推荐
- emacs 图解
			
emacs 图解 =================== End
 - MT【76】直线系
			
解答 :答案是3,4.
 - 学习Spring Boot:(十六)使用Shiro与JWT 实现认证服务
			
前言 需要把Web应用做成无状态的,即服务器端无状态,就是说服务器端不会存储像会话这种东西,而是每次请求时access_token进行资源访问.这里我们将使用 JWT 1,基于散列的消息认证码,使用一 ...
 - 【BZOJ1296】[SCOI2009]粉刷匠(动态规划)
			
[BZOJ1296][SCOI2009]粉刷匠(动态规划) 题面 BZOJ 洛谷 题解 一眼题吧. 对于每个串做一次\(dp\),求出这个串刷若干次次能够达到的最大值,然后背包合并所有的结果即可. # ...
 - 【BZOJ1293】[SCOI2009]生日礼物(单调队列)
			
[BZOJ1293][SCOI2009]生日礼物(单调队列) 题面 BZOJ 洛谷 题解 离散之后随便拿单调队列维护一下就好了. #include<iostream> #include&l ...
 - BZOJ 2039 [2009国家集训队]employ人员雇佣 网络流
			
链接 BZOJ 2039 题解 这题建图好神,自己瞎搞了半天,最后不得不求教了企鹅学长的博客,,,,发现建图太神了!! s向每个人连sum(e[i][x]) 的边,每个人向T连a[i]的边.两两人之间 ...
 - GDKOI2018发烧记
			
偏远小渔村NOIP螺旋升天选手又一次来到了广州参加GDKOI...金实的初三爷们也来啦?要被碾啦T T Day 0 跟HR Lao爷拼(biao)车到了高铁站,上了高铁居然没有颓颓颓吃吃吃(雾),安心 ...
 - IIS并发连接数及性能优化
			
如果要查看IIS连接数,最简单方便的方法是通过“网站统计”来查看,“网站统计”的当前在线人数可以认为是当前IIS连接数.然而,“网站统计”的当前在线人数统计时间较长,一般为10分钟或15分钟,再加上统 ...
 - activiti 用户手册中 10分钟 小例子 简单代码搭建 及 其中的 各种坑
			
看mossle的 5.16 用户手册中的 快速起步:10分钟教程 想自己跑一下,虽然官方文档已经写的非常详细了,但是实际操作中还是遇到各种坑,这里记录下来. 首先官网下载最新的 5版本 full G ...
 - UML类图学习笔记
			
http://note.youdao.com/noteshare?id=d5af220db7081dda73511fcb7b4da390