[NOIP-P0708]新的开始

题目描述

发展采矿业当然首先得有矿井,小FF花了上次探险获得的千分之一的财富请人在岛上挖了n口矿井,但他似乎忘记考虑的矿井供电问题……

    为了保证电力的供应,小FF想到了两种办法:

    1、在这一口矿井上建立一个发电站,费用为v(发电站的输出功率可以供给任意多个矿井)。

    2、将这口矿井与另外的已经有电力供应的矿井之间建立电网,费用为p。

小FF希望身为”NewBe_One" 计划首席工程师的你帮他想出一个保证所有矿井电力供应的最小花费。

输入

第一行一个整数n,表示矿井总数。

    第2~n+1行,每行一个整数,第i个数v[i]表示在第i口矿井上建立发电站的费用。

    接下来为一个n*n的矩阵P,其中p[i,j]表示在第i口矿井和第j口矿井之间建立电网的费用(数据保证有p[i,j] = p[j,i], 且 p[i,i]=0)。

输出

仅一个整数,表示让所有矿井获得充足电能的最小花费。

样例输入

4
    5 
    4
    4 
    3 
    0 2 2 2 
    2 0 3 3 
    2 3 0 4 
    2 3 4 0

样例输出

9

提示

n <= 300 v[i], p <= 10^5

代码

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=(j);i<=(k);++i)
#define per(i,j,k) for(register int i=(j);i>=(k);--i)
using namespace std;
template<class T> inline void read(T &x)
{
    x=0;
    register char c=getchar();
    register bool f=0;
    while(!isdigit(c))f^=c=='-',c=getchar();
    while(isdigit(c))x=x*10+c-'0',c=getchar();
    if(f)x=-x;
}
#define ll long long
const ll inf=1e18;
const int N=303;
ll n,v[N],f[N][N],dis[N],tot;
bool used[N];
inline void prim()
{
    rep(i,1,n)
        dis[i]=f[1][i];
    dis[1]=0,used[1]=1;
    rep(i,1,n-1)
    {
        ll mn=inf,k=-1;
        rep(j,1,n)
            if(!used[j]&&mn>dis[j])
                mn=dis[j],k=j;
        used[k]=1,tot+=mn;
        rep(j,1,n)
            if(!used[j]&&dis[j]>f[k][j]&&f[k][j]>0)
                dis[j]=f[k][j];
    }
} 
int main()
{
  
    read(n);
    rep(i,1,n)
    {
        read(f[i][n+1]);
        f[n+1][i]=f[i][n+1];
    }
    rep(i,1,n)
        rep(j,1,n)
            read(f[i][j]);
    ++n;
    prim();
    printf("%d\n",tot);
    return 0;
}
上一篇:F - Strange Memory


下一篇:线路规划--最小生成树(克鲁斯卡尔)