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;
    }
  • 相关阅读:
    八数码难题 (codevs 1225)题解
    小木棍 (codevs 3498)题解
    sliding windows (poj 2823) 题解
    集合删数 (vijos 1545) 题解
    合并果子 (codevs 1063) 题解
    等价表达式 (codevs 1107)题解
    生理周期 (poj 1006) 题解
    区间 (vijos 1439) 题解
    区间覆盖问题 题解
    种树 (codevs 1653) 题解
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10056152.html
Copyright © 2011-2022 走看看