soj3366: Watering Hole_最小生成树Prim

来源:互联网 发布:淘宝子账户和主账户 编辑:程序博客网 时间:2024/05/21 14:45

soj3366: Watering Hole

http://acm.scu.edu.cn/soj/problem.action?id=3366

简介题意,农夫John要给他的几个牧场引水,到底是挖井还是挖管子呢,n个农场,每个地方挖井的钱,每段挖管子的钱已知,求最少花多少钱啦。

每个地方挖井?可以想象加一个点,这个点到各个点的距离是挖井的价格,那就相当于n+1个农场求最小生成树啦。就相当于把每个挖井的价格当做多一点,连线的权值。大不了画个四个点的图,再加一个点,瞬间就明白咯。

#include<cstdio>#include<cstring>using namespace std;#define INF 0x3f3f3f3f#define MAX 310int map[MAX][MAX];int dist[MAX];bool visit[MAX];void prim(int n){    memset(dist,INF,sizeof(dist));    memset(visit,0,sizeof(visit));    for(int i = 1;i <= n; i++)        if(map[1][i] != 0)            dist[i] = map[1][i];    visit[1] = 1;    int res = 0;    for(int i = 1;i <= n; i++)    {        int x;        int minx = INF;        for(int j = 1;j <= n; j++)            if(!visit[j]&&dist[j] < minx)            {                minx = dist[j];                x = j;            }        if(minx < INF)        {            visit[x] = 1;            res += minx;            for(int j = 1;j <= n; j++)            {                if(!visit[j]&&map[x][j]!=0&&map[x][j]<dist[j])                    dist[j] = map[x][j];            }        }    }    printf("%d\n",res);}int main(){    int n;    while(~scanf("%d",&n))    {        memset(map,0,sizeof(map));        for(int i = 1;i <= n; i++)        {            int a;            scanf("%d",&a);            map[n+1][i] = map[i][n+1] = a;        }        for(int i = 1;i <= n; i++)            for(int j = 1;j <= n; j++)                scanf("%d",&map[i][j]);        n++;        prim(n);    }    return 0;}
和昨天那道题几乎一模一样的,prim,主要在于想通把每个点的权值拉伸看成直线。

原创粉丝点击