zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 55 (Rated for Div. 2):D. Maximum Diameter Graph

    D. Maximum Diameter Graph

    题目链接https://codeforces.com/contest/1082/problem/D

    题意:

    给出n个点的最大入度数,要求添加边构成一个无环无向无重边的图,并且最大化图中的最短路径。

    题解:

    要求最短路径最大,我们会想到把每一个允许入度可以大于1的点先连起来,形成一个”链“,当前肯定满足条件,并且两端点的最短路径长度是所有情况中最大的。

    然后对于入度为1的点,先尽量考虑放在链的两端,然后再在中间随便插入。

    代码如下:

    先附上自己用邻接矩阵存储的丑代码。。。代码思路比较直接:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 505;
    int Map[N][N],vis[N],a[N];
    int n;
    
    int main(){
        scanf("%d",&n);
        int cnt = 0,tot = 0,st = 0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            if(a[i]==1) cnt++;
            else st=i;
        }
        vis[st]=1;bool flag=false;
        int end=st;
        for(int i=st;;i=end){
            if(flag) break;
            int tmp=0;
            for(int j=1;j<=n;j++){
                if(a[j]>1 && !vis[j]){
                    tmp++;
                    Map[i][j]=Map[j][i]=1;
                    vis[j]=1;
                    a[i]--;a[j]--;
                    end=j;
                    break;
                }
            }
            if(!tmp) flag=true;
        }
        int tmp = 0;
        for(int i=1;i<=n;i++) if(vis[i]) tot+=a[i],tmp++;
        if(cnt>tot){
            cout<<"NO";
            return 0;
        }
        int ans,edges=tmp-1;
        if(cnt>1) ans=edges+2;
        else if(cnt==1) ans=edges+1;
        else ans=edges;
        cout<<"YES"<<" "<<ans<<endl;
        if(cnt){
            cnt--;
            for(int i=1;i<=n;i++) if(!vis[i]){
                vis[i]=Map[i][st]=Map[st][i]=1;
                edges++;
                a[st]--;a[i]--;
                break ;
            }
            if(cnt){
                cnt--;
                for(int i=1;i<=n;i++) if(!vis[i]){
                    vis[i]=Map[i][end]=Map[end][i]=1;
                    edges++;
                    a[end]--;a[i]--;
                    break;
                }
            }
            if(cnt){
                for(int i=n;i>=1;i--) if(!vis[i]){
                    vis[i]=1;
                    for(int j=1;j<=n;j++){
                        if(a[j] && vis[j] &&j!=i){
                            edges++;
                            Map[j][i]=Map[i][j]=1;
                            a[j]--;a[i]--;
                            break;
                        }
                    }
                }
            }
        }
        cout<<edges<<endl;
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                if(Map[i][j]) printf("%d %d
    ",i,j);
        return 0;
    }
    View Code

    再来一个O(N)的算法,注意一下代码的细节,直接像链一样连边:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 505;
    int a[N];
    int n,sum;
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i];
        if(sum<2*(n-1)){
            cout<<"NO";return 0;
        }
        vector <int> ones;
        for(int i=1;i<=n;i++){
            if(a[i]==1) a[i]=0 , ones.push_back(i);
        }
        int t=ones.size();
        printf("YES %d
    %d
    ",n-t-1+min(t,2),n-1);
        int st=0;
        if(!ones.empty()){
            st=ones.back();
            ones.pop_back();
        }
        for(int i=1;i<=n;i++){//从起点开始添边形成一个链
            if(a[i]>1){
                if(st){
                    a[st]--;a[i]--;
                    printf("%d %d
    ",st,i);
                }
                st=i;
            }
        }
        for(int i=n;i>=1;i--){ // 从尾开始添加(在链上) 
            while(a[i]>0 && !ones.empty()){
                a[i]--;
                int now1 = ones.back();ones.pop_back();
                printf("%d %d
    ",i,now1);
            }
        }
        return 0;
    }
  • 相关阅读:
    Cisco 交换机配置的基本命令
    Mysql读写分离方案-Amoeba环境部署记录
    centos7下部署zabbix3.4+grafana
    Docker
    Linux 安装源码软件
    mysql 日志
    mysql导出导入数据
    mysql 数据库的备份和还原
    Mysql 数据库管理
    英语单词
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10056152.html
Copyright © 2011-2022 走看看