C题意:
给定n个点(标号0~n-1)的度数(就是与其邻接的点的个数)和所有与它邻接的点标号的异或和,求满足这些条件的树的边应该是怎么连的,将边输出出来
这里可以理解成拓扑排序的方式考虑,当i度数为1的时候,那么我们必然知道 i 肯定得与s[i]相连使其剩余的异或值为0
所以建立一个队列不断将度数变为1的点放进来,得到边以后,不断更新点的度数和其对应的异或和的值
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int N = (1<<16); 5 int n,degree[N] , s[N] , vis[N]; 6 #define pii pair<int,int> 7 vector<pii> v; 8 queue<int> q; 9 int main() 10 { 11 // freopen("a.in" , "r" , stdin); 12 scanf("%d" , &n); 13 for(int i=0 ; i<n ; i++){ 14 scanf("%d%d" , °ree[i] , &s[i]); 15 if(degree[i]==1) q.push(i); 16 } 17 while(!q.empty()){ 18 int u = q.front(); 19 q.pop(); 20 // cout<<u<<" "<<degree[u]<<" "<<s[u]<<endl; 21 if(degree[u]==0) continue; 22 degree[u]--; 23 if(!vis[s[u]]){ 24 degree[s[u]]-- , s[s[u]]^=u; 25 if(degree[s[u]]==1) q.push(s[u]) , vis[s[u]]=1; 26 } 27 else degree[s[u]]--; 28 v.push_back(make_pair(u , s[u])); 29 } 30 printf("%d\n" , v.size()); 31 for(int i=0 ; i<v.size() ; i++) 32 printf("%d %d\n" , v[i].first , v[i].second); 33 return 0; 34 }