ural 1982. Electrification Plan -最小生成树

来源:互联网 发布:js 金币掉落效果 编辑:程序博客网 时间:2024/06/04 19:03

1982. Electrification Plan

Time limit: 0.5 second
Memory limit: 64 MB

Some country has n cities. The government has decided to electrify all these cities. At first, power stations ink different cities were built. The other cities should be connected with the power stations via power lines. For any citiesi, j it is possible to build a power line between them in cij roubles. The country is in crisis after a civil war, so the government decided to build only a few power lines. Of course from every city there must be a path along the lines to some city with a power station. Find the minimum possible cost to build all necessary power lines.

Input

The first line contains integers n and k (1 ≤ kn ≤ 100). The second line contains k different integers that are the numbers of the cities with power stations. The nextn lines contain an n × n table of integers {cij} (0 ≤cij ≤ 105). It is guaranteed thatcij = cji, cij > 0 forij, cii = 0.

Output

Output the minimum cost to electrify all the cities.

Sample

inputoutput
4 21 40 2 4 32 0 5 24 5 0 13 2 1 0
3
Problem Author: Mikhail Rubinchik
Problem Source: Open Ural FU Championship 2013
Tags: graph theory  (
hide tags for unsolved problems
)


题意:
n个城市,其中k个城市有发电站,问,怎么才能让每个城市都有电,并且花费最小


解题思路
每个有发电站的城市都能做出一个最小生成树来,然后好几个最小生成树。但是这样不好写
我们设置一个超级发电站,一开始所有发电站都与之相连,让超级发电站当这课树的根,
这样,既达到了将好几棵树变成一棵树的目的,又使得发电站与发电站之间边的权值不会被加进结果去
然后用 kruskl 算法做最小生成树,
这里注意,因为是从边权值最小开始,权值最小的边的节点的父亲可能都不是超级发电站,
所以后期遇到一个以超级发电站为父亲节点的,要让不是超级发电站为父亲节点的连进去。(有点乱,见代码)


代码
#include <iostream>#include <cstdio>#include <cstring>#include <functional>#include <algorithm>#include <bits/stdc++.h>using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 110;int n,k;int fa[maxn];int suroot;int root[maxn];void init(){    for(int i = 0;i<maxn;i++){        ///让所有发电站都以超级发电站为父亲        ///这样就不会把发电站与发电站之间连线了,相当于多个生成树了        if(root[i]) fa[i] = suroot;        else            fa[i] = i;    }}struct edge{    int u,v,cost;}e[maxn*maxn];bool comp(const edge& e1,const edge& e2){    return e1.cost < e2.cost;}int findp(int x){    int xp = x;    while(fa[xp] != xp){        xp = fa[xp];    }    int nowx = x,newx;    while(fa[nowx] != xp){        newx = fa[nowx];        fa[nowx] = xp;        nowx = newx;    }    return xp;}int main(){    scanf("%d%d",&n,&k);    for(int i = 0;i<k;++i){        scanf("%d",&suroot);///指定一个超级发电站,只要是发电站就好,无所谓哪个        root[suroot] = 1;    }    init();///初始化父亲    int E = 0;///边的编号,一共E条边,下标到E-1    for(int i = 1;i<=n;++i){        for(int j=1;j<=n;++j){            int t;            scanf("%d",&t);            e[E].u = i;            e[E].v = j;            e[E].cost = t;            E++;        }    }    sort(e,e+E,comp);    int res = 0;    for(int i = 0; i<E; i++){        edge te = e[i];        int fu = findp(te.u),fv = findp(te.v);        if(fu == fv) continue;///因为可能最小的边连得不是超级发电站,///所以当我们遇到一个父亲是超级发电站的时候,///再让超级发电站当 根 父亲        if(fu == suroot){            fa[fv] = fu;            res += te.cost;        }        else if(fv == suroot){            fa[fu] = fv;            res += te.cost;        }        else{            fa[fu] = fv;            res += te.cost;        }    }    printf("%d",res);    return 0;}




1 0
原创粉丝点击