• 2019牛客多校训练(四)


    比赛链接:

    https://ac.nowcoder.com/acm/contest/884#question

    A. meeting

    题意:

    给出一颗树

    让所有染色点到某个点的最大距离最小

    分析:

    结果为最远点对的距离除二向上取整

    假设有最远点对的路径上的中间点

    如果有某个点它到这个中间点要远,那么最远点对就不是最远点对了,产生矛盾

    利用树上点对路径唯一性,两次$dfs$求出染色点直径

    ac代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define pa pair<int,int>
    using namespace std;
    const int maxn=1e5+10;
    const ll mod=1e9+7;
    struct Edge{
        int to,nex;
    }edge[maxn*2];
    int n,k,edge_num,head[maxn],dis[maxn],cor[maxn];
    void add_edge(int u,int v)
    {
        edge_num++;
        edge[edge_num].nex=head[u];
        edge[edge_num].to=v;
        head[u]=edge_num;
    }
    void dfs(int x){
        for(int i=head[x];i;i=edge[i].nex){
            int to=edge[i].to;
            if(dis[to]>dis[x]+1)dis[to]=dis[x]+1,dfs(to);
        }
    }
    int fin(int x)
    {
        for(int i=1;i<=n;i++)dis[i]=1e9;
        dis[x]=0;
        dfs(x);
        int maxx=0,inde;
        for(int i=1;i<=k;i++)
            if(maxx<dis[cor[i]])maxx=dis[cor[i]],inde=cor[i];
        //for(int i=1;i<=k;i++)cout<<dis[cor[i]]<<" ";
        //cout<<endl;
        return inde;
    }
    int main()
    {
        scanf("%d %d",&n,&k);
        for(int i=1;i<=n-1;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            add_edge(u,v);
            add_edge(v,u);
        }
        for(int i=1;i<=k;i++)scanf("%d",&cor[i]);
       // cout<<k<<endl;
        int node1=fin(cor[1]);
        int node2=fin(node1);
      //  cout<<node1<<" "<<node2<<endl;
        printf("%d
    ",(dis[node2]+1)/2);
        return 0;
    }
    

      

    D. triples I

    题意:

    用尽可能少的三的倍数异或出$a$

    分析:

    典型的构造题

    首先,$2^{n}\%3$等于1或者2

    1.如果$a\%3=0$,直接输出$a$

    2.如果$a\%3=1$,去掉二进制某些位置,让$a$变成3的倍数即可

    3.$a\%3=1$同理

    ac代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define pa pair<int,int>
    using namespace std;
    const int maxn=3e6+10;
    const ll mod=1e9+7;
    vector<ll>ve1,ve2;
    int main()
    {
       // cout<<(48|24)<<endl;
        //cout<<((ll)1<<62)<<endl;
        int T;
        scanf("%d",&T);
        while(T--){
            ll a;
            scanf("%lld",&a);
            if(a%3==0){
                printf("1 %lld
    ",a);
                continue;
            }
            ve1.clear(),ve2.clear();
            for(int i=0;i<=62;i++){
                if(a&((ll)1<<i)){
                    if(((ll)1<<i)%3==2)ve2.push_back((ll)1<<i);
                    else ve1.push_back((ll)1<<i);
                }
            }
            printf("2 ");
            if(a%3==1){
                if(ve1.size()>=2){
                    printf("%lld %lld
    ",a-ve1[0],a-ve1[1]);
                }else if(ve1.size()==1){
                    printf("%lld %lld
    ",a-ve1[0],a-ve2[0]-ve2[1]);
                }else if(ve1.size()==0){
                    printf("%lld %lld
    ",a-ve2[0]-ve2[1],a-ve2[2]-ve2[3]);
                }
            }
            else {
                if(ve2.size()>=2){
                    printf("%lld %lld
    ",a-ve2[0],a-ve2[1]);
                }else if(ve2.size()==1){
                    printf("%lld %lld
    ",a-ve2[0],a-ve1[0]-ve1[1]);
                }else if(ve2.size()==0){
                    printf("%lld %lld
    ",a-ve1[0]-ve1[1],a-ve1[2]-ve1[3]);
                }
            }
    
        }
        return 0;
    }
    	triples I
    

    J. free

    题意:

    给出一个图,最多让$k$条边花费变成0,求$s$到$t$的最短距离

    分析:

    对整个图分层,分成$k+1$层,第0层节点编号是$1$到$n$,第二次是$n+1$到$n+n$

    建立层之间的边,并且允许第i层的点用0花费到达$i+1$层

    调用迪杰斯特拉,最后的结果是$dis[k*n+t]$

    ac代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define pa pair<int,int>
    using namespace std;
    const int maxn=2e6+10;
    const ll mod=1e9+7;
    int n,m,s,t,k,head[maxn],edge_num,dis[maxn];
    bool vis[maxn];
    struct Edge{
        int to,w,nex;
    }edge[maxn*5];
    void add_edge(int u,int v,int w)
    {
       // cout<<"adge:"<<u<<" "<<v<<" "<<w<<endl;
        edge_num++;
        edge[edge_num].nex=head[u];
        edge[edge_num].to=v;
        edge[edge_num].w=w;
        head[u]=edge_num;
    }
    void dj()
    {
        for(int i=1;i<=k*n+n;i++)dis[i]=1e9,vis[i]=0;
        priority_queue<pa>que;
        dis[s]=0;
        que.push(make_pair(0,s));
        while(que.size()){
            pa now=que.top();
            que.pop();
     
            if(vis[now.second])continue;
            vis[now.second]=1;
           // cout<<now.second<<endl;
            for(int i=head[now.second];i;i=edge[i].nex){
                int to=edge[i].to;
                int w=edge[i].w;
                if(dis[to]>dis[now.second]+w){
                    dis[to]=dis[now.second]+w;
                    que.push(make_pair(-dis[to],to));
                }
            }
     
        }
    }
    int main()
    {
        scanf("%d %d %d %d %d",&n,&m,&s,&t,&k);
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
            for(int j=0;j<=k;j++){
                add_edge(u+j*n,v+j*n,w);
                add_edge(v+j*n,u+j*n,w);
                if(j!=k){
                    add_edge(u+j*n,v+(j+1)*n,0);
                    add_edge(v+j*n,u+(j+1)*n,0);
                }
            }
        }
        dj();
        printf("%d
    ",dis[k*n+t]);
        return 0;
    }
    

      

  • 相关阅读:
    从发布订阅模式到redux(一)
    swipper的一个小坑
    代码精进之路读后感(二)
    代码精进之路读后感(一)
    编译提示没有对应的构造函数
    静态成员函数里面不能使用非静态的成员变量
    越精简越好
    MediaTypeListWidget->insertItem 添加的label没有填充单元格
    避免代码后期过分改动的方法
    Qt的index 用方法static_cast<CTableItem*>(index.internalPointer())取出来的值的成员都未初始化
  • 原文地址:https://www.cnblogs.com/carcar/p/11256879.html
Copyright © 2020-2023  润新知