Noip模拟考试7:解题报告

1 . 二叉树
( ( binary .cpp/c/pas)
【问题描述】
二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的结点。
完全二叉树:只有最下面的两层结点度能够小于2,并且最下面一层的结点
都集中在该层最左边的若干位置的二叉树。

给出N个数,且这N个数构成1至N的排列。现在需要你按顺序构建一棵二叉
排序树,并按照层次遍历的方式输出它,然后判断它是否是一棵完全二叉树。

【输入格式】
输入文件名为binary.in。
输入文件包含两行。第一行为一个正整数N;第二行为1至N的排列。
【输出格式】
输出文件名为binary.out。
输出文件包含两行。第一行为构建出的二叉排序树的层次遍历;第二行判
断是否是完全二叉树:若是输出yes,否则输出no。

解题:二叉树实现建树。观察可知若maxo>n则输出no

maxo=n则输入yes

#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxm 1100010
#define maxn 25
using namespace std;
int n,b,dep,deep,flag,Jud,maxo;
int tree[maxm],a[maxn];
void build(int o,int now)
{
    if(!tree[o])
    {
        tree[o]=now;
        maxo=max(maxo,o);
        return ;
    }
    if(now<tree[o])build(o<<1,now);
    else build(o<<1|1,now);
    return ;
}
int main()
{
//    freopen("binary.in","r",stdin);
//    freopen("binary.out","w",stdout);
    scanf("%d",&n);
    for(int i = 1 ; i <= n ; ++i)
        scanf("%d",&a[i]);
    tree[1]=a[1];
    for(int i = 2 ; i <= n ; ++i)
        build(1,a[i]);
    for(int i = 1 ; i<=maxo; ++i)
        {
            if(!tree[i])continue;
            printf("%d ",tree[i]);
        }
    if(maxo>n)printf("\nno");
    else printf("\nyes");
    return 0;
}

2 2 . 列车调度
(manage.cpp/c/pas)
【问题描述】
有N辆列车,标记为1,2,3,…,N。它们按照一定的次序进站,站台共有K个轨
道,轨道遵从 先进先出的原则。列车进入站台内的轨道后可以等待任意时间后出
站,且所有列车不可后退。现在要使出站的顺序变为N,N-1,N-2,…,1,询问K的
最小值是多少。
例如上图中进站的顺序为1,3,2,4,8,6,9,5,7,则出站的顺序变为
9,8,7,6,5,4,3,2,1。
【输入格式】
输入文件名为manage.in。
输入共2行。
第 1 行包含1个正整数N,表示N辆列车。
第 2 行包含N个正整数,为1至N的一个排列,表示进站次序。
【输出格式】
输出文件名为manage.out。
输出共1行,包含1个整数,表示站台内轨道数K的最小值。

由于每次寻找轨道中大于当前序号的最小序号,所以用二分查找实现。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int ans,top,n,a[200005],q[200005];
int main()
{
//    freopen("manage.in","r",stdin);
//    freopen("manage.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int l,r;
    top=1;
    q[1]=a[1];
    for(int i=2;i<=n;i++){
        if(a[i]>q[top])
        {
            q[++top]=a[i];
            continue;
        }
        l=0;r=top;
        while(r-l>1){
            int m=(l+r)>>1;
            if(q[m]<a[i])l=m;
            else r=m;
        }
        q[r]=a[i];
    }
    printf("%d",top);
    return 0;
}

3. 保留道路
(road .cpp/c/pas)
【问题描述】
很久很久以前有一个国家,这个国家有N个城市,城市由1,2,3,…,N标号,
城市间有M条双向道路,每条道路都有两个属性g和s,两个城市间可能有多条道
路,并且可能存在将某一城市与其自身连接起来的道路。后来由于战争的原因,
国王不得不下令减小花费从而关闭一些道路,但是必须要保证任意两个城市相互
可达。
道路花费的计算公式为wG*max{所有剩下道路的属性g}+wS*max{所有剩下道
路的属性s},其中wG和wS是给定的值。国王想要在满足连通性的前提下使这个花
费最小,现在需要你计算出这个花费。
【输入格式】
输入文件名为road.in。
第一行包含两个正整数N和M。
第二行包含两个正整数wG和wS。
后面的M行每行描述一条道路,包含四个正整数u,v,g,s,分别表示道路连接
的两个城市以及道路的两个属性。
【输出格式】
输出文件名为road.out。
输出一个整数,表示最小花费。若无论如何不能满足连通性,输出-1。

解题:

初步考虑kruskal,由于影响因素有两个,所以我们对g 进行sort,再维护s。

每一次加边的时候,我们先将加入边存入一个维护s从小到大的数组中,然后进行kruskal,再判断边数是否=n-1,若等于n-1则更新答案。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 50010
#define maxm 410
#define inf 1ll<<60
#define ll long long
using namespace std;
int num,top;
ll ans=inf;
int fa[maxm],st[maxm],n,m;
ll wg,ws;
struct edge{
    int u,v,g,s;
}a[maxn];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
bool cmp(edge x,edge y){return x.g<y.g;}
int main()
{
//    freopen("road.in","r",stdin);
//    freopen("road.out","w",stdout);
    scanf("%d%d",&n,&m);
    scanf("%I64d%I64d",&wg,&ws);
    for(int i = 1 ; i <= m ; ++i)
        scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].g ,&a[i].s );
    sort(a+1,a+1+m,cmp);
    top=0;
    for(int i = 1 ; i <= m ; ++i)
    {
        int j;
        for( j = 1 ; j <= n ; ++j)
            fa[j]=j;
        for( j = top ; j >= 1 ; --j)
        {
            if(a[st[j]].s >a[i].s)
                st[j+1]=st[j];
            else break;
        }
        top++;st[j+1]=i;
        num=0;
        for(int j = 1 ; j <= top ; ++j)
        {
            int fx=find(a[st[j]].u );
            int fy=find(a[st[j]].v );
            if(fx!=fy)
            {
                fa[fx]=fy;
                st[++num]=st[j];
            }
        }
        if(num==n-1)
            ans=min(ans,wg*a[i].g+ws*a[st[num]].s);
        top=num;
    }
    if(ans==inf)printf("-1");
    else printf("%I64d",ans);
    return 0;
}

 

posted @ 2017-08-19 17:28  傅judge  阅读(244)  评论(0编辑  收藏  举报