欢迎来到endl的博客hhh☀☾☽♡♥

浏览器标题切换
把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

20200727模拟

题目

木材

会议

重建

命名

wood.cpp

meeting.cpp

build.cpp

内存

128M

128M

128M

时限

1s

1s

1s

 

1、木材(wood.cpp(源自洛谷P2440 木材加工

题目描述

木材厂有一些原木,现在想把这些木头切割成一些长度相同的小段木头(木头有可能有剩余),需要得到的小段的数目是给定的。当然,我们希望得到的小段木头越长越好,你的任务是计算能够得到的小段木头的最大长度。木头长度的单位是cm。原木的长度都是正整数,我们要求切割得到的小段木头的长度也是正整数。

例如有两根原木长度分别为11和21,要求切割成到等长的6段,很明显能切割出来的小段木头长度最长为5.

输入格式

第一行是两个正整数N和K(1 ≤ N ≤ 100000,1 ≤ K ≤ 100000000),N是原木的数目,K是需要得到的小段的数目。

接下来的N行,每行有一个1到100000000之间的正整数,表示一根原木的长度。

输出格式

能够切割得到的小段的最大长度。如果连1cm长的小段都切不出来,输出”0”。

输入输出样例

输入

3 7

232

124

456

输出

114


 

 典型二分

#include<bits/stdc++.h>
#define R register int
#define ll long long
using namespace std;
const int N=1e6+5;
int k,n,a[N];
ll sum;
int read()
{
    int f=1;char ch;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')f=-1;
    int res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';
    return res*f;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
bool judge(int x)
{
    int ans=0;
    for(R i=1;i<=n;i++)
    {
        ans+=a[i]/x;
        if(ans>=k)return true;
    }
    return ans>=k;
}
int main()
{
    //freopen("wood.in","r",stdin);
    //freopen("wood.out","w",stdout);
    n=read();k=read();
    for(R i=1;i<=n;i++)
    {
        a[i]=read();
        sum+=a[i];
    }
    int l=0,r=sum/n;//注意这里的r不是a[i]中的最小值
    while(l<r)
    {
        int mid=(l+r+1)>>1;
        if(judge(mid))l=mid;
        else r=mid-1;
    }
    write(l);
    return 0;
}
AC代码

 

2、会议(meeting.cpp(源自洛谷P1395 会议

题目描述

有一个村庄居住着n个村民,有n-1条路径使得这n个村民的家联通,每条路径的长度都为1。现在村长希望在某个村民家中召开一场会议,村长希望所有村民到会议地点的距离之和最小,那么村长应该要把会议地点设置在哪个村民的家中,并且这个距离总和最小是多少?若有多个节点都满足条件,则选择节点编号最小的那个点。

输入格式

第一行。一个数n,表示有n个村民。

接下来n-1行,每行两个数字a和b,表示村民a的家和村民b的家之间存在一条路径。

输出格式

一行输出两个数字x和y

x表示村长将会在哪个村民家中举办会议

y表示距离之和的最小值

输入输出样例

输入

4

1 2

2 3

3 4

输出

2 4

说明/提示

【数据范围】

70%数据n<=1000

100%数据n<=50000


 

 

#include<bits/stdc++.h>
#define R register int
#define ll long long
using namespace std;
const int N=1e6+5;
int n,d[50005],ans,mi=0x3f3f3f3f;
int read()
{
    int f=1;char ch;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')f=-1;
    int res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';
    return res*f;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
int g[1001][1001];
int main()
{
    //freopen("meeting.in","r",stdin);
    //freopen("meeting.out","w",stdout);
    
    n=read();
    memset(g,0x3f,sizeof(g));
    for(R i=1;i<n;i++)
    {
        int x=read(),y=read();
        g[x][y]=1;g[y][x]=1;
    }
    for(R k=1;k<=n;k++)
    {
        for(R i=1;i<=n;i++)
        if(i!=k)
        {
            for(R j=1;j<=n;j++)
            if(i!=j&&j!=k)
            {
                g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
            }
        }
    }
    for(R i=1;i<=n;i++)
    {
        for(R j=1;j<=n;j++)
        if(i!=j)
        {
            d[i]+=g[i][j];
        }
        if(d[i]<mi)
        {
            ans=i;
            mi=d[i];
        }
    }
    write(ans);putchar(' ');write(mi);
    return 0;
}
Floyd40分代码
#include<bits/stdc++.h>
#define R register int
using namespace std;
const int N=1e6+5;
int mi=0x3f3f3f3f;
int read()
{
    int f=1;char ch;
    while((ch=getchar())>'9'||ch<'0')if(ch=='-')f=-1;
    int res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';
    return res*f;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
struct node{
    int id,dis;
    bool operator <(const node &a)const
    {
        return dis>a.dis;
    }
};

int n,head[N],d[N],cnt,k;
bool v[N];
struct edge{
    int to,nxt,dis;
}e[N];
void add(int a,int b,int w)
{
    e[++cnt].nxt=head[a];
    e[cnt].to=b;
    e[cnt].dis=w;
    head[a]=cnt;
}
void dj(int s)
{
    priority_queue<node> q;
    memset(d,0x3f,sizeof(d));
    memset(v,false,sizeof(v));
    d[s]=0;q.push((node){s,0});
    while(!q.empty())
    {
        node now=q.top();q.pop();
        if(v[now.id])continue;
        v[now.id]=true;
        for(R i=head[now.id];i;i=e[i].nxt)
        {
            int to=e[i].to;
            if(d[to]>d[now.id]+e[i].dis)
            {
                d[to]=d[now.id]+e[i].dis;
                q.push((node){to,d[to]});
            }
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(R i=1;i<n;i++)
    {
        int a,b;scanf("%d%d",&a,&b);
        add(a,b,1);add(b,a,1);
    }
    for(R i=1;i<=n;i++)//没啥好说的,就暴力枚举
    {
        dj(i);
        int ans=0;
        for(int j=1;j<=n;j++)if(i!=j)ans+=d[j];
        if(ans<mi)
        {
            k=i;
            mi=ans;
        }
    }
    write(k);putchar(' ');write(mi);
    return 0;
}
优化后的dijkstra70分代码

正解其实只有关键的一行代码:f[son]=f[fa]+n-2*size[son](详解可见该题解

#include<bits/stdc++.h>
#define R register int
using namespace std;
const int N=1e6+5;
int read()
{
    int f=1;char ch;
    while((ch=getchar())>'9'||ch<'0')if(ch=='-')f=-1;
    int res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';
    return res*f;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}

int n,head[N],d[N],cnt,k,size[N],f[N];
bool v[N];
struct edge{
    int to,nxt,dis;
}e[N];
void add(int a,int b)
{
    e[++cnt].nxt=head[a];
    e[cnt].to=b;
    head[a]=cnt;
}
void build(int x)
{
    size[x]=1;
    for(R i=head[x];i;i=e[i].nxt)
    {
        int to=e[i].to;
        if(d[to])continue;
        d[to]=d[x]+1;
        build(to);
        size[x]+=size[to];
    }
}
void dfs(int son,int fa)
{
    f[son]=f[fa]+n-2*size[son];
    for(R i=head[son];i;i=e[i].nxt)
    {
        int to=e[i].to;
        if(to==fa)continue;
        dfs(to,son);
    }
}
int main()
{
    n=read();
    int k=1,ma=0;
    for(R i=1;i<n;i++)
    {
        int a=read(),b=read();
        add(a,b);add(b,a);
    }
    d[1]=1;build(1);
    for(R i=1;i<=n;i++)ma+=d[i];
    ma-=n;f[1]=ma;
    for(R i=head[1];i;i=e[i].nxt)
    {
        int to=e[i].to;
        dfs(to,1);
    }
    for(R i=2;i<=n;i++)
    {
        if(f[i]<ma)
        {
            ma=f[i];
            k=i;
        }
    }
    write(k);putchar(' ');write(ma);
    return 0;
}
AC代码

 

3、重建(build.cpp(源自洛谷P1119 灾后重建

题目背景

B地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响。但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车。换句话说,只有连接着两个重建完成的村庄的公路才能通车,只能到达重建完成的村庄。

题目描述

给出B地区的村庄数N,村庄编号从0到N-1,和所有M条公路的长度,公路是双向的。并给出第i个村庄重建完成的时间ti​,你可以认为是同时开始重建并在第ti天重建完成,并且在当天即可通车。若ti为0则说明地震未对此地区造成损坏,一开始就可以通车。之后有Q个询问(x, y, t),对于每个询问你要回答在第t天,从村庄x到村庄的最短路径长度为多少。如果无法找到从x村庄到y村庄的路径,经过若干个已重建完成的村庄,或者村庄x或村庄y在第t天仍未重建完成 ,则需要返回-1。

输入格式

第一行包含两个正整数N,M,表示了村庄的数目与公路的数量。

第二行包含N个非负整数t0, t1,…, tN-1,表示了每个村庄重建完成的时间,数据保证了t0 ≤ t1 ≤ … ≤ tN-1​。

接下来M行,每行3个非负整数i, j, w,w为不超过10000的正整数,表示了有一条连接村庄i与村庄j的道路,长度为w,保证i≠j,且对于任意一对村庄只会存在一条道路。

接下来一行也就是M+3行包含一个正整数Q,表示Q个询问。

接下来Q行,每行3个非负整数x, y, t,询问在第t天,从村庄x到村庄y的最短路径长度为多少,数据保证了t是不下降的。

输出格式

共Q行,对每一个询问(x, y, t)输出对应的答案,即在第t天,从村庄x到村庄y的最短路径长度为多少。如果在第t天无法找到从x村庄到y村庄的路径,经过若干个已重建完成的村庄,或者村庄x或村庄y在第t天仍未修复完成,则输出-1。

输入输出样例

输入

4 5

1 2 3 4

0 2 1

2 3 1

3 1 2

2 1 4

0 3 5

4

2 0 2

0 1 2

0 1 3

0 1 4

输出

-1

-1

5

4

说明/提示

对于30%的数据,有N≤50;

对于30%的数据,有ti= 0,其中有20%的数据有ti = 0且N>50;

对于50%的数据,有Q≤100;

对于100%的数据,有N≤200,M≤N×(N-1)/2,Q≤50000,所有输入数据涉及整数均不超过100000。


 

啊没想到Floyd竟然是正解!然而我还是改了好几次才A的 555

#include<bits/stdc++.h>
#define R register int
#define ll long long
using namespace std;
const int N=1e6+5,inf=0x3f3f3f3f;
int n,m,q,g[205][205],t[205];
int read()
{
    int f=1;char ch;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')f=-1;
    int res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';
    return res*f;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
int main()
{
    //freopen("build.in","r",stdin);
    //freopen("build.out","w",stdout);
    n=read();m=read();
    memset(g,0x3f,sizeof(g));
    for(R i=0;i<n;i++)t[i]=read();
    for(R i=1;i<=m;i++)
    {
        int x=read(),y=read(),w=read();
        g[x][y]=w;g[y][x]=w;
    }
    q=read();
    int num=0,k=0;
    while(q--)
    {
        
        int x=read(),y=read(),ti=read();

        while(t[num]<=ti&&num<n)num++;
        for(;k<num;k++)
        {
            for(R i=0;i<n;i++)
            if(i!=k)
            {
                for(R j=0;j<n;j++)
                if(i!=j&&j!=k)
                {
                    g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
                }
            }
        }
        if(ti<t[x]||ti<t[y]||g[x][y]>=inf/2)printf("-1\n");
        else if(x==y)printf("0\n");
        else write(g[x][y]),putchar('\n');
    }
    return 0;
}
AC代码
posted @ 2020-07-29 10:52  endl\n  阅读(194)  评论(0编辑  收藏  举报