zoukankan      html  css  js  c++  java
  • 洛谷 题解 P1550 【[USACO08OCT]打井Watering Hole】

    本题看似很难,实际上思路非常简单——如果你想通了。

    首先有一个问题:图中有几个点?大部分的人会回答(n)个点。错了,有(n+1)个。

    多出来的那个点在哪?关键在于你要理解每一个决策的意义。实际上,多出来的那个点是地下的天然矿泉水。当我们打井时,我们实际上是在往地下连边。理解了这一点,代码就没有任何难度了。

    构图时,我们只需多加一个点,对于每个点(i),我们连边(i→n+1),边权为(w_i)。然后直接跑最小生成树就没了。就没了。(转载from here)

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=300+10;
    const int MAXM=1e5;
    int n,m;
    int fa[MAXN];
    struct Node
    {
    	int u,v,w;
    	bool operator < (const Node &x) const
    	{
    		return x.w>w;
    	}
    }edge[MAXM];
    inline int read()
    {
    	int tot=0;
    	char c=getchar();
    	while(c<'0'||c>'9')
    		c=getchar();
    	while(c>='0'&&c<='9')
    	{
    		tot=tot*10+c-'0';
    		c=getchar();
    	}
    	return tot;
    }
    inline int find(int k)
    {
    	if(fa[k]==k)return k;
    	else return fa[k]=find(fa[k]);
    }
    inline int kruskal()
    {
    	int tot=0,cnt=0;
    	for(int i=1;i<=n;i++)
    		fa[i]=i;
    	for(int i=1;i<=m;i++)
    	{
    		int fx=find(edge[i].u),fy=find(edge[i].v);
    		if(fx!=fy)
    		{
    			fa[fx]=fy;
    			tot++;
    			cnt+=edge[i].w;
    		}
    		if(tot==n-1)return cnt;
    	}
    }
    int main()
    {
    	n=read();
    	int x;
    	for(int i=1;i<=n;i++)
    	{
    		x=read();
    		edge[++m].u=i;
    		edge[m].v=n+1;
    		edge[m].w=x;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			x=read();
    			if(i<j)
    			{
    				edge[++m].u=i;
    				edge[m].v=j;
    				edge[m].w=x;
    			}
    		}
    	}
    	n++;
    	sort(edge+1,edge+1+m);
    	printf("%d
    ",kruskal());
    	return 0;
    }
    
  • 相关阅读:
    std::copy 多次赋值 偏移 内存分配
    chromium http 处理
    c++ 智能指针 传参
    最简单的gn构建 脱离chromium
    简单的nodejs httpserver
    C语言跨文件调用变量方法
    使用node压缩js
    Jmeter压力测试工具安装及使用教程
    前端常见跨域解决方案(全)
    QuickApp 快应用中 或 nodejs 中 API接品调用时 GBK转UTF8
  • 原文地址:https://www.cnblogs.com/hulean/p/11128642.html
Copyright © 2011-2022 走看看