H

- 题目大意

    给你一个r * c的格子,每个格子有一个 ‘ ’ 或者 ‘/’ 的墙,以及打掉墙的费用,问使得所有块联通的最小费用。(自己可以配合图来看好理解一点)

- 解题思路

    我们可以将其转化成联通块的问题,就是把每个格子看成两部分,左侧和右侧。以一行来看,假设两个格子A,B。那么B格子的右侧的编号一定和A格子的左侧的编号相同。给每个格子的左右侧标上号,然后加入边,边的两个端点为一个格子的两个编号。权值为墙的费用然后处理行与行之间的边,然后假设上边格子为A,下面格子为B。那么如果A是‘/’,B是’/’,那么A的右格子和B的左格子是相通的,这时候加一条边,将权值设为0就可以了。(注意位置和数组大小!!!)

- 代码

#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
using namespace std;
const int MAX = 1e6;
int fa[MAX];
string str[400];
int num[150][150];
int sum,sum1,cnt;
void init()
{
	for (int i = 1; i <= MAX; i++)
	{
		fa[i] = i;
	}
	cnt=0;
}

struct Edge {
	int u, v, w;
	bool operator<(const Edge &rhs)const {
		return w < rhs.w;
	}
}e[MAX];

struct Edge2{
       int u,v;

}maps[150][150];
void addEdge(int u,int v,int w)
{
    e[cnt].v=v;
    e[cnt].u=u;
    e[cnt++].w=w;
}
int find(int x)
{
	if (x == fa[x])
		return x;
	else
		return fa[x] = find(fa[x]);
}

bool Union(int x, int y)
{
	int fx = find(x), fy = find(y);
	if (fx == fy)
		return false;
	fa[fx] = fy;
	return true;
}

void kruskal(int m)
{
	sort(e, e + m);
		for (int i = 0; i < m; i++)
		{
			int u = e[i].u, v = e[i].v, w = e[i].w;
			if (Union(u, v))
			{
				sum +=w;
		}
	}
}

int main()
{
	int t,n, m;
	scanf("%d",&t);
for(int q=1;q<=t;q++)
{
    scanf("%d%d",&n,&m);
    init();
    for(int i=0;i<n;i++)
    {
    cin>>str[i];
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
        scanf("%d",&num[i][j]);
        }
    }
		int p = 1;
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				if (j == 0)
				{
					maps[i][j].u = p++;
					maps[i][j].v = p++;
					addEdge(maps[i][j].u, maps[i][j].v, num[i][j]);
				}
				else
				{
					maps[i][j].u = maps[i][j - 1].v;
					maps[i][j].v = p++;
					addEdge(maps[i][j].u, maps[i][j].v, num[i][j]);
				}
				if (i != 0)
				{
					if (str[i - 1][j] == '/')
					{
						if (str[i][j] == '/')
						{
							addEdge(maps[i][j].u, maps[i - 1][j].v, 0);
						}
						else
						{
							addEdge(maps[i][j].v, maps[i - 1][j].v, 0);
						}
					}
					else
					{
						if (str[i][j] == '/')
						{
							addEdge(maps[i][j].u, maps[i - 1][j].u, 0);
						}
						else
						{
							addEdge(maps[i][j].v, maps[i - 1][j].u, 0);
						}
					}
				}
			}
		}
		sum=0;
		kruskal(cnt);
		printf("Case %d: %d
",q,sum);
}
	return 0;
}

  

原文地址:https://www.cnblogs.com/alpacadh/p/8449455.html