Codeforces gym101755F Tree Restoration(拓扑排序)
题意:
一棵树,给出每个点的后代们,问你这棵树是否存在,存在就给出这棵树
n<=1000
思路:
对祖先->后代建立有向图,跑拓扑排序。跑的时候不断更新父亲并判断答案的存在性,同时注意一种情况:一个点他儿子是他的后代,同样也得是他父亲的后代,这样传递下去就一定是所有祖宗的后代。
代码:
代码参考网上的
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #include<functional> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 #define lowbit(x) ((x)&(-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 1e9+7; const int maxn = 1e6+100; const int maxm = 1e6+100; //const int inf = 0x3f3f3f3f; const int inf = 1e9+7; const db pi = acos(-1.0); int n; vector<int>v[maxn]; int f[maxn]; int ma[1111][1111]; int d[maxn]; int root; bool sv(){ queue<int>q; for(int i = 1; i <= n; i++){ if(d[i]==0)q.push(i); } if(q.size()!=1)return false; root = q.front(); while(!q.empty()){ int top = q.front(); q.pop(); for(int i = 0; i < v[top].size(); i++){ int x = v[top][i]; d[x]--; if(f[x]!=-1&&!ma[f[x]][top])return false; f[x] = top; if(d[x]==0)q.push(x); } } for(int i = 1; i <= n; i++){ if(d[i]!=0)return false; }f[root]=0; for(int i = 1; i <= n; i++){ //if(i!=root){ for(int j = 0; j < v[i].size(); j++){ if(!ma[f[i]][v[i][j]]){ //printf("--%d %d %d\n",i,f[i],v[i][j]); return false; } } //} } return true; } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++){ ma[0][i] = 1; f[i] = -1; int k; scanf("%d", &k); for(int j = 1; j <= k; j++){ int x; scanf("%d", &x); v[i].pb(x); d[x]++; ma[i][x]=1; } } mem(f,-1); if(sv()){printf("YES\n"); for(int i = 1; i <= n; i++){ if(i==root)continue; printf("%d %d\n",f[i],i); }} else printf("NO"); return 0; } /* 4 2 2 3 2 3 4 1 4 0 */