1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| #include<queue> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std;
const int N=1e5,INF=(1<<29),SZ=2*N+10;
struct EDGE{ int to,cap; EDGE *nxt,*rev; EDGE(){} EDGE(int _t,int _c,EDGE *_n,EDGE *_r):to(_t),cap(_c),nxt(_n),rev(_r){} }; struct GRAPH{ EDGE edg[4*N*2+10],*head[SZ],*ncnt; GRAPH(){ncnt=edg;} void AddEdge(int u,int v,int cap){ EDGE *p=++ncnt,*q=++ncnt; *p=EDGE(v,cap,head[u],q);head[u]=p; *q=EDGE(u, 0,head[v],p);head[v]=q; } EDGE* operator [](int id){return head[id];} }; GRAPH Gr; EDGE *cop[SZ]; int dis[SZ]; vector< pair<int,int> > lnk[N+3]; int n,S,T,tot; vector<int> tset[N+3]; int ans[N+3][2]; bool vis[N+3];
int Aug(int u,int in){ if(u==T) return in; int out=0; while(cop[u]){ EDGE *it=cop[u];cop[u]=cop[u]->nxt; int v=it->to; if(dis[v]!=dis[u]+1 || it->cap<=0) continue; int tov=Aug(v,min(in-out,it->cap)); it->cap-=tov;it->rev->cap+=tov; out+=tov; if(out==in) break; } return out; } bool BFS(){ for(int i=1;i<=T;i++) dis[i]=-1,cop[i]=Gr[i]; queue<int> que;que.push(S);dis[S]=0; while(!que.empty()){ int u=que.front();que.pop(); for(EDGE *it=Gr[u];it;it=it->nxt){ int v=it->to; if(dis[v]!=-1 || it->cap<=0) continue; dis[v]=dis[u]+1; if(v==T) return true; que.push(v); } } return false; } int Dinic(){ int res=0; while(BFS()) res+=Aug(S,INF); return res; } void DFS(int u){ vis[u]=true;tot++; for(int i=(int)lnk[u].size()-1;i>=0;i--){ int v=lnk[u][i].first,id=lnk[u][i].second; if(ans[id][0] || vis[v]) continue; ans[id][0]=u;ans[id][1]=v; DFS(v); } } int main(){ scanf("%d",&n); S=n*2;T=S+1; for(int i=2;i<=n;i++) Gr.AddEdge(S,i,1); for(int i=1;i<n;i++) Gr.AddEdge(i+n,T,1); for(int i=1;i<n;i++){ int num;scanf("%d",&num); while(num--){ int u;scanf("%d",&u); Gr.AddEdge(u,n+i,1); tset[i].push_back(u); } } int res=Dinic(); if(res<n-1) printf("-1\n"); else{ for(int i=1;i<n;i++){ int E=i+n,u=-1; for(EDGE *it=Gr[E];it && u==-1;it=it->nxt) if(it->cap) u=it->to; for(int j=(int)tset[i].size()-1;j>=0;j--) if(tset[i][j]!=u){ int v=tset[i][j]; lnk[u].emplace_back(v,i); lnk[v].emplace_back(u,i); } } DFS(1); if(tot<n) printf("-1\n"); else for(int i=1;i<n;i++) printf("%d %d\n",ans[i][0],ans[i][1]); } return 0; }
|