codeforces 501C. Misha and Forest 解题报告
2024-09-10 16:03:43
题目链接:http://codeforces.com/problemset/problem/501/C
题目意思:有 n 个点,编号为 0 ~ n-1。给出 n 个点的度数(即有多少个点跟它有边相连)以及跟它相连的点的编号的异或结果。最后需要输出整幅图的所有边的情况。
这道题确实是一道很好的题目!!!!它说拓扑排序的变形,需要队列的运用,还有就是异或计算的性质!!!(非一般厉害)
由于是无向无环的简单图,换言之就是一棵树啦^_^。那么它就肯定有叶子结点,叶子节点的度数为1,此时它相邻点的异或结果实际上就是所求点的编号了。然后把跟叶子节点相邻的点的度数-1,代表把叶子节点去除,此时异或结果是有变的。需要用本来的异或结果跟该叶子节点再异或一次,就得出除了这个叶子节点外其他点的异或值了。举个例子吧,假如有一幅图是这样的。
0 的相邻点有1、 2、 3,异或出来的结果是0,它的度数是3.那么当处理0-1这条边时,容易知道去除1这个点后,只有2和3异或了:10 ^ 11 = 1,刚好等于 1 ^ 2 ^ 3 ^ 1 (01 ^ 10 ^ 11 ^ 01)。异或的一个性质就是a^b^c^a = b ^ c。是不是很神奇呢~~~~当然我们总是处理那些度数为1的点,把这些点放入队列里面,依次处理。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std; #define f first
#define s second const int maxn = (<<) + ;
int degree[maxn], XOR_sum[maxn]; int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE int n;
while (scanf("%d", &n) != EOF) {
queue<int> q;
pair<int, int> ans[maxn];
for (int i = ; i < n; i++) {
scanf("%d%d", °ree[i], &XOR_sum[i]);
if (degree[i] == )
q.push(i);
}
int cnt = ;
while (!q.empty()) {
int from = q.front();
q.pop();
if (degree[from] == ) { // 这句判断很重要,因为有可能degree[]--过程中使得变为0
int to = XOR_sum[from];
ans[cnt].f = from;
ans[cnt++].s = to;
degree[to]--;
XOR_sum[to] ^= from; // 异或性质
if (degree[to] == )
q.push(to);
}
}
printf("%d\n", cnt);
for (int i = ; i < cnt; i++)
printf("%d %d\n", ans[i].f, ans[i].s);
}
return ;
}
最新文章
- 【LeetCode】Roman to Integer &; Integer to Roman
- JVM快速学习
- Sass学习之路(1)——Sass简介
- php基础29:打开目录
- cumber + selenium +java自动化测试
- poco vs Boost
- tiny210V2 Uboot kernel filesystem 烧写和启动
- Loadrunner之脚本的调试和保存(六)
- [编织消息框架][netty源码分析]14 PoolChunk 的 PoolSubpage
- 邓_thinkphp口试
- CSS布局(一) 盒子模型
- 《mongoDB》索引
- python3.6和pip3安装
- 微信小程序之 动画 —— 自定义底部弹出层
- webpack新手入门——配置及安装
- Java 经典练习题_Day010
- MySQL的库、表详细操作
- hihocoder1478 水陆距离
- 洛谷P2495 [SDOI2011]消耗战(虚树)
- 区块链开发(七)truffle使用入门汇总