歌名 - 歌手
0:00

    【NOIP2014模拟8.24】小X 的道路修建

    题目

    因为一场不小的地震,Y 省n 个城市之间的道路都损坏掉了,省长希望小X 将城市之间的道路重修一遍。
    很多城市之间的地基都被地震破坏导致不能修路了,因此可供修建的道路只有m 条。因为施工队伍有限,省长要求用尽量少的道路将所有的城市连通起来,这样施工量就可以尽量少。不过,省长为了表示自己的公正无私,要求在满足上述条件的情况下,选择一种方案,使得该方案中最贵道路的价格和最便宜道路的价格的差值尽量小,即使这样的方案会使总价提升很多也没关系。
    小X 现在手忙脚乱,希望你帮帮他。

    分析

    我们将边按权值从小到大排序
    将边一条条加入,
    当当前边的两个端点在原树中有路径相连时,如果加入的当前边,就会形成一个环,
    所以将当前边的两个端点在原树中的路径中的最大一条边删掉,这样就能保证差值尽量小。
    然后,如果形成了一棵树,就将当前边的边权(因为排了序,当前边的边权一定最大)-树中最小的边权来更新答案。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const int maxlongint=2147483647;
    const int mo=1000000007;
    const int N=3005;
    using namespace std;
    int k,n,m,fa[N*N*2],a[N][N*2],ans;
    int z[8][2]=
    {
    	{-1,0},
    	{0,-1},
    	{1,0},
    	{0,1},
    	{-1,1},
    	{1,-1},
    	{1,1},
    	{-1,-1}
    };
    int pos(int x,int y)
    {
    	return (x-1)*m*2+y;
    }
    int get(int x)
    {
    	if(fa[x]==x) return x;
    	fa[x]=get(fa[x]);
    	return fa[x];
    }
    int main()
    {
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=1;i<=n*m*2;i++) fa[i]=i;
    	for(k=k;k>=1;k--)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		int xx=x,yy=y+m;
    		bool q=true;
    		for(int i=0;i<=7 && q;i++)
    			if(a[x+z[i][0]][(y+z[i][1]-1+2*m)%(2*m)+1])
    			{
    				int xf=get(pos(x+z[i][0],(y+z[i][1]-1+2*m)%(2*m)+1));
    				for(int j=0;j<=7 && q;j++)
    					if(a[xx+z[j][0]][(yy+z[j][1]-1+2*m)%(2*m)+1])
    					{
    						int yf=get(pos(xx+z[j][0],(yy+z[j][1]-1+2*m)%(2*m)+1));
    						if(xf==yf) q=false;
    					}
    			}
    		if(q)
    		{
    			a[x][y]=a[xx][yy]=1;
    			for(int i=0;i<=7;i++)
    				if(a[x+z[i][0]][(y+z[i][1]-1+2*m)%(2*m)+1])
    				{
    					int xf=get(pos(x+z[i][0],(y+z[i][1]-1+2*m)%(2*m)+1));
    					fa[xf]=pos(x,y);
    				}
    			for(int j=0;j<=7;j++)
    				if(a[xx+z[j][0]][(yy+z[j][1]-1+2*m)%(2*m)+1])
    				{
    					int yf=get(pos(xx+z[j][0],(yy+z[j][1]-1+2*m)%(2*m)+1));
    					fa[yf]=pos(xx,yy);
    				}
    			ans++;
    		}
    	}
    	cout<<ans<<endl;
    }
    
    
    posted @ 2018-05-22 12:11  无尽的蓝黄  阅读(181)  评论(0编辑  收藏  举报