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" , &degree[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 }
cf 501C

相关文章: