题目大意:
给出一个无向图,每条边有一个花费,每个点有一个花费,求最小花费使得此图分为几个联通块。
每个联通块的额外花费为此联通块内点的最小花费。
思路:
建一个虚点,向其它点连每个点的花费,然后跑最小生成树就行了
c o d e code code
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int n, dis[2010], ans, minn=1e9;
priority_queue<pair<int, int> > q;
int head[2010], tot;
bool v[2010];
struct node
{
int from, to, next, w;
}b[1000010];
int a[2010];
void add(int x, int y, int w)
{
b[++tot]=(node){x, y, head[x], w};
head[x]=tot;
}
int main()
{
scanf("%d", &n);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
int x;
scanf("%d", &x);
add(i, j, x);
}
for(int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
for(int j=1; j<=n; j++)
if(i!=j)
add(j, i, a[i]);
}
for(int i=1; i<=n; i++)
add(n+1, i, a[i]);
while(!q.empty())
q.pop();
memset(dis, 0x3f, sizeof(dis));
dis[n+1]=0;
q.push(make_pair(0, n+1));
tot=0;
ans=0;
while(!q.empty())
{
int x=q.top().second;
q.pop();
if(v[x])
continue;
v[x]=1;
ans+=dis[x];
tot++;
for(int i=head[x]; i; i=b[i].next)
{
int y=b[i].to;
if(dis[y]>b[i].w&&!v[y])
{
dis[y]=b[i].w;
q.push(make_pair(-dis[y], y));
}
}
if(tot==n+1)
break;
}
printf("%d", ans);
return 0;
}