码迷,mamicode.com
首页 > 其他好文 > 详细

寒假培训之 模拟赛2

时间:2018-02-28 21:40:51      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:out   ios   kruskal   std   space   opened   close   gpo   不能   

T1,T3不提。

T2城市建设,注意:

1.城市建造顺序按h从大到小排序,顺序与边无关;
2.i,j之间连边的代价为:(h[i]>h[j]) (b[i]+b[j])*r+(a[i]-b[i])*b[j]*h[i]+(a[j]-b[j])*a[i]*h[j];
3.赋好边权后跑最小生成树

错误代码如下:

技术分享图片
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,ct,head[55],sid[55][55],r,fa[55],ep[3100];
long long ans;
char dc;
struct N{
    int hd,to,next,w;
}edge[3100];
struct C{
    int b,a,h,pos;
}p[55];
bool cmp(C x,C y)
{
    return x.h>y.h;
}
bool cmp2(int x,int y)
{
    return edge[x].w<edge[y].w;
}
int find(int x)
{
    if(fa[x]==x)return x;
    return fa[x]=find(fa[x]);
}
void add(int x,int y,long long w)
{
    ct++;
    edge[ct].hd=x;
    edge[ct].to=y;
    edge[ct].w=w;
    edge[ct].next=head[x];
    head[x]=ct;
}
long long cl(int i)
{
    long long tot=0;
    for(int k=0;k<p[i].a-p[i].b;k++)
        tot+=p[i].h*(p[i].b+k);
    return tot;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&p[i].b),fa[i]=i,p[i].pos=i;//存p的位置 
    for(int i=1;i<=n;i++)
        scanf("%d",&p[i].a);
    for(int i=1;i<=n;i++)
        scanf("%d ",&p[i].h);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            scanf("%c",&dc);
            if(dc==Y)
            {
                sid[i][j]=1;//i和j有直接相连的边 
                fa[i]=find(j);
            }
            if(j==n)scanf("%c",&dc);
        }
    scanf("%d",&r);
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)//
        {
            if(find(i)!=find(j))
            {
                int u,v;
                if(p[i].h>p[j].h)u=i,v=j;//先建造u的房子 
                else u=j,v=i;
                long long tot=0;
                tot+=p[u].h*(p[u].a-p[u].b)*p[v].b;//边权 
                tot+=p[v].h*(p[v].a-p[v].b)*p[u].a;
                tot+=r*(p[u].b+p[v].b);
                add(u,v,tot);
            }
        }
    for(int i=1;i<=ct;i++)ep[i]=i;
    sort(ep+1,ep+ct+1,cmp2);//ep记录edge的角标,将ep排序 
    for(int i=1;i<=ct;i++)//Kruskal 
    {
        int u=edge[ep[i]].hd;
        int v=edge[ep[i]].to;
        if(find(u)!=find(v))
        {
            fa[find(u)]=find(v);
            sid[u][v]=1;//有直接相连的边 
            sid[v][u]=1;
            ans+=r*(p[u].b+p[v].b);//ans加上连边的代价 
        }
    }
    sort(p+1,p+n+1,cmp);//按h排序 
    for(int i=1;i<=n;i++)
    {
        long long tot=0;
        for(int j=1;j<=n;j++)
        {
            if(!sid[p[i].pos][p[j].pos])continue;
            tot+=p[i].h*p[j].b*(p[i].a-p[i].b);//总代价加上连向此点的代价 
        }
        tot+=cl(i);//自己本身建造房子的代价 
        p[i].b=p[i].a;//之后用此点的b改变 
        ans+=tot;
    }
    printf("%lld",ans);
    return 0;
}
View Code

正确代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,ct,fa[60];
long long ans,r;
char dc;
struct N{
	int hd,to,next;
	long long w;
}edge[3800];
struct C{
	long long b,a,h;
}p[60];
bool cmp(N x,N y)
{
	return x.w<y.w;
}
int find(int x)
{
	if(fa[x]==x)return x;
	return fa[x]=find(fa[x]);
}
void add(int x,int y,long long w)
{
	ct++;
	edge[ct].hd=x;
	edge[ct].to=y;
	edge[ct].w=w;
}
long long cl(int i)
{
	return p[i].h*(p[i].a+p[i].b-1)*(p[i].a-p[i].b)/2;
}
int main()
{
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld",&p[i].b),fa[i]=i;
	for(int i=1;i<=n;i++)
		scanf("%lld",&p[i].a);
	for(int i=1;i<=n;i++)
		scanf("%lld ",&p[i].h),ans+=cl(i);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		{
			scanf("%c",&dc);
			if(i<j&&dc==‘Y‘)
			{
				ans+=min(p[i].h*p[j].b*(p[i].a-p[i].b)+p[j].h*p[i].a*(p[j].a-p[j].b),
						p[j].h*p[i].b*(p[j].a-p[j].b)+p[i].h*p[j].a*(p[i].a-p[i].b));
				fa[find(i)]=find(j);//不能写fa[i]=find(j)! 
			}
			if(j==n)scanf("%c",&dc);
		}
	scanf("%lld",&r);
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++)//
		{
			if(find(i)!=find(j))
			{
				long long tot=0;
				tot+=min(p[i].h*p[j].b*(p[i].a-p[i].b)+p[j].h*p[i].a*(p[j].a-p[j].b),
						p[j].h*p[i].b*(p[j].a-p[j].b)+p[i].h*p[j].a*(p[i].a-p[i].b));
				tot+=r*(p[i].b+p[j].b);
				add(i,j,tot);
			}
		}
	sort(edge+1,edge+ct+1,cmp);
	for(int i=1;i<=ct;i++)
	{
		int u=edge[i].hd;
		int v=edge[i].to;
		if(find(u)!=find(v))
		{
			ans+=edge[i].w;
			fa[find(u)]=find(v);
		}
	}
	printf("%lld",ans);
	return 0;
}

  

寒假培训之 模拟赛2

标签:out   ios   kruskal   std   space   opened   close   gpo   不能   

原文地址:https://www.cnblogs.com/Zinn/p/8485673.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!