zoukankan      html  css  js  c++  java
  • 【NOIP2015模拟10.22】最小代价

    前言

    本来在比赛上就想到最小生成树了,但不相信这道题那么简单,然后就没有然后了。。。

    题目

    给出一幅由n个点m条边构成的无向带权图。
    其中有些点是黑点,其他点是白点。
    现在每个白点都要与他距离最近的黑点通过最短路连接(如果有很多个黑点,可以选取其中任意一个),我们想要使得花费的代价最小。请问这个最小代价是多少?
    注意:最后选出的边保证每个白点到离它最近的黑点的距离仍然等于原图中的最短距离。

    分析

    这道题最麻烦的地方就是最终搞成的图有可能有很多个联通块。
    

    增加一个点:0点,让0点连接所有的黑点,边权为0;
    处理从S发到每个点的最短距离
    题目要求最小的总距离,显然搞一遍最小生成树就可以了。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const long long maxlongint=2147483747;
    using namespace std;
    long long b[710000][4],dis[710000],next[710000],last[710000],a[710000],fa[710000],ans,tot,n,m,v[710000],d[8000000];
    bool bz[710000];
    void q(long long l,long long r)
    {
    	long long i=l,j=r;
    	long long mid=b[(l+r)/2][0],e;
    	while(i<j)
    	{
    		while(b[i][0]<mid) i++;
    		while(b[j][0]>mid) j--;
    		if(i<=j)
    		{
    			e=b[i][0];
    			b[i][0]=b[j][0];
    			b[j][0]=e;
    			e=b[i][1];
    			b[i][1]=b[j][1];
    			b[j][1]=e;
    			e=b[i][2];
    			b[i][2]=b[j][2];
    			b[j][2]=e;
    			i++;
    			j--;
    		}
    	}
    	if(i<r) q(i,r);
    	if(l<j) q(l,j);
    }
    int spfa()
    {
    	long long head=0,tail=1,k;
    	fill(dis,dis+n+m+1,maxlongint*3);
    	fill(bz,bz+n+m+1,true);
    	d[1]=0;
    	dis[0]=0;
    	while(head<tail)
    	{
    		k=d[++head];
    		bz[k]=true;
    		for(long long i=last[k];i;i=next[i])
    		{
    			if(dis[a[i]]>dis[k]+v[i])
    			{
    				dis[a[i]]=dis[k]+v[i];
    				if(bz[a[i]])
    				{
    					d[++tail]=a[i];
    					bz[a[i]]=false;
    				}
    			}
    		}
    	}
    }
    bool dg(long long x)
    {
    	long long i,j;
    	for(i=last[x];i;i=next[i])
    	{
    		long long y=a[i];
    		if(dis[x]+v[i]==dis[y])
    		{
    			dg(y);
    			b[++tot][1]=x;
    			b[tot][2]=y;
    			b[tot][0]=v[i];
    		}
    	}
    	return true;
    }
    long long get(long long x)
    {
    	if(x==fa[x]) return x;
    	long long y=get(fa[x]);
    	fa[x]=y;
    	return y;
    }
    int kruskal()
    {
    	long long i,j,k,l,x,y;
    	for(i=1;i<=tot;i++)
    	{
    		x=get(b[i][1]);
    		y=get(b[i][2]);
    		if(x!=y)
    		{
    			ans+=b[i][0];
    			fa[y]=x;
    		}
    	}
    }
    int bj(long long x,long long y,long long k)
    {
    	fa[y]=y;
    	next[++tot]=last[x];
    	last[x]=tot;
    	v[tot]=k;
    	a[tot]=y;
    }
    int main()
    {
    	scanf("%lld%lld",&n,&m);
    	long long i,j,k,l,x,y;
    	for(i=1;i<=n;i++)
    	{
    		scanf("%lld",&x);
    		if(x) bj(0,i,0);
    	}
    	for(i=1;i<=m;i++)
    	{
    		scanf("%lld%lld%lld",&x,&y,&k);
    		bj(x,y,k);
    		bj(y,x,k);
    	}
    	spfa();
    	tot=0;
    	dg(0);
    	q(1,tot);
    	bool b1=maxlongint;
    	kruskal();
    	if(ans==0) cout<<"impossible";else
    		cout<<ans;
    }
    
    
  • 相关阅读:
    Qt BarChart实践
    Qt Charts_Audio实践
    Qt 报错LINK2019:无法解析的外部符号
    Qt Charts实践
    Qt Qwdget 汽车仪表知识点拆解8 淡入效果
    因果图法设计测试用例
    Jsoup获取部分页面数据失败 Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml
    loadrunner入门篇
    如何对jmeter设置IP欺骗
    jmeter录制移动端脚本
  • 原文地址:https://www.cnblogs.com/chen1352/p/9008607.html
Copyright © 2011-2022 走看看