zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    [总结] XPO (eXpress Persistent Objects) 学习总结一
    [总结]工作中常用的正则表达式,有了它事半功倍!
    用JS实现页面滚动位置保持的方法
    [总结]TLF论坛全功略,下载指南!
    Javascript里使用Dom操作Xml
    。NET构架相关资源
    [收藏]关于用Asp.Net论坛发帖软件的实现
    匹配Unicode字符的正则表达式(中文)
    [转贴]如何实现TreeView的双击事件?
    [转贴]客户端不装adobe reader,打开pdf文件的插件
  • 原文地址:https://www.cnblogs.com/alpacadh/p/8449455.html
Copyright © 2011-2022 走看看