博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

hackerrank DFS Edges

瞬间移动

题意:要求构造一个图,使其dfs树中有t条树边,b条返祖边,f条前向边,c条其他边。

 

膜了题解才会,好神啊。

考虑所有结点的深度之和,这个值必须介于$[max(b,f+t),C^{2}_{n}-c]$之间。按照这个构造树以后就容易了。

 

#include<vector>
#include<cstdio>
#include<algorithm>
#define MN 110000
using namespace std;

int n,t,b,f,c,to[MN],top,mi;
vector<int> v[MN],e[MN];
void dfs(int x){
    to[++top]=x;
    for (int i=1;i<top&&b;i++) e[x].push_back(to[i]),b--;
    for (int i=1;i<top-1&&f;i++) e[to[i]].push_back(x),f--;
    for (int i=0;i<v[x].size();i++) dfs(v[x][i]);
    top--;
}
void DFS(int x){
    to[++top]=x;
    for (int i=0;i<v[x].size();i++) DFS(v[x][i]);
}
void _DFS(int x){
    for (int i=1;i<=top&&c;i++) e[x].push_back(to[i]),c--;
    for (int i=0;i<v[x].size();i++) _DFS(v[x][i]);
}
int main(){
    scanf("%d%d%d%d",&t,&b,&f,&c);n=t+1;
    mi=max(b,f+t);
    if (1LL*n*(n-1)/2-c<mi) return puts("-1"),0;
    to[top=1]=1;
    for (int i=2;i<=n;i++){
        int s=min(mi-(n-i),top);
        mi-=s;v[to[s]].push_back(i);
        if (s==top) to[++top]=i;
    }
    top=0;
    dfs(1);
    for (int i=1;i<=n&&c;i++){
        for (int j=0;j<v[i].size()&&c;j++){
            top=0;
            for (int k=0;k<j;k++) DFS(v[i][k]);
            _DFS(v[i][j]);
        }
    }
    printf("%d\n",n);
    for (int i=1;i<=n;i++){
        printf("%d",v[i].size()+e[i].size());
        for (int j=0;j<v[i].size();j++) printf(" %d",v[i][j]);
        for (int j=0;j<e[i].size();j++) printf(" %d",e[i][j]);puts("");
    }
}
View Code

 

posted @ 2017-06-30 10:53  swm_sxt  阅读(221)  评论(0编辑  收藏  举报