CodeForces Round #285 Div.2

C.Misha and Forest (图论 BFS)

比赛进行了一半才想起来有场CF没打,=_=||

前两道题快速切掉,C题一直卡没什么好的思路

憋了几天,忍不住偷偷瞄了一下别人AC的代码,发现我题没看清题目,题中说了给出的图是森林。

于是切入点找到了!

 

题意:

一个由n个节点构成的森林,编号从0到n-1,给出每个节点的 度数 和 相邻节点编号的异或和,输出图中的边数和所有邻接节点的编号。

 

分析:

因为是森林,所以图中的叶子节点就是突破口。叶子节点最明显的特征就是:

  • 度数为1
  • 它相邻节点编号的异或和 就是 它唯一的邻居本身的编号

这样就找到一条边。

所以我们就可以像剥洋葱一样,把外面的叶子节点一层一层的剥去。

可以用一个队列来维护,开始将所有的叶子节点入队,然后逐个向内拓展。如果将这个叶子节点去掉后又出现新的叶子节点,则将新节点入队,直到队列为空。

 1 #include <cstdio>
 2 
 3 const int maxn = (1 << 16) + 10;
 4 
 5 int degree[maxn], xorsum[maxn];
 6 int edge[maxn][2], cnt = 0;
 7 int Q[maxn], head = 0, tail = 0;
 8 int main()
 9 {
10     int n;
11     scanf("%d", &n);
12     for(int i = 0; i < n; i++)
13     {
14         scanf("%d%d", &degree[i], &xorsum[i]);
15         if(degree[i] == 1) Q[tail++] = i;
16     }
17 
18     while(head < tail)
19     {
20         int t = Q[head++];
21         if(degree[t] == 0) continue;
22         degree[t] = 0;
23         int neighbor = xorsum[t];
24         edge[cnt][0] = t; edge[cnt++][1] = neighbor;
25         degree[neighbor]--;
26         xorsum[neighbor] ^= t;
27         if(degree[neighbor] == 1) Q[tail++] = neighbor;
28     }
29 
30     printf("%d\n", cnt);
31     for(int i = 0; i < cnt; ++i) printf("%d %d\n", edge[i][0], edge[i][1]);
32 
33     return 0;
34 }
代码君

 

转载于:https://www.cnblogs.com/AOQNRMGYXLMV/p/4229749.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值