题意:要求构造一个图,使其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); 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(""); } }