您的位置:首页 > 其它

Codeforces 501C:Misha and Forest(好题+思维+异或的运算规律+树)

2016-09-28 22:52 435 查看
C. Misha and Forest

time limit per test
1 second

memory limit per test
256 megabytes

input
standard input

output
standard output

Let's define a forest as a non-directed acyclic graph (also without loops and parallel edges). One day Misha played with the forest consisting of n vertices.
For each vertex v from 0 to n - 1 he
wrote down two integers, degreev and sv,
were the first integer is the number of vertices adjacent to vertex v, and the second integer is the XOR sum of the numbers of vertices
adjacent to v (if there were no adjacent vertices, he wrote down 0).

Next day Misha couldn't remember what graph he initially had. Misha has values degreev and sv left,
though. Help him find the number of edges and the edges of the initial graph. It is guaranteed that there exists a forest that corresponds to the numbers written by Misha.

Input

The first line contains integer n (1 ≤ n ≤ 216),
the number of vertices in the graph.

The i-th of the next lines contains numbers degreei and si (0 ≤ degreei ≤ n - 1, 0 ≤ si < 216),
separated by a space.

Output

In the first line print number m, the number of edges of the graph.

Next print m lines, each containing two distinct numbers, a and b (0 ≤ a ≤ n - 1, 0 ≤ b ≤ n - 1),
corresponding to edge (a, b).

Edges can be printed in any order; vertices of the edge can also be printed in any order.

Examples

input
3
2 3
1 0
1 0


output
2
1 0
2 0


input
2
1 1
1 0


output
1
0 1


Note

The XOR sum of numbers is the result of bitwise adding numbers modulo 2. This operation exists in many modern programming languages. For example,
in languages C++, Java and Python it is represented as "^", and in Pascal — as "xor".

题目大意:给你一个数字n,代表n个节点,编号为0~n-1,接下来n行,分别对应每个节点的信息,每行两个数字,第一个数字是与该点连接的点的个数,第二个数字是与该点连接的所有点的异或结果,让你求出该图的边的条数和每条边的两端编号。(注:题中说明该图是无向无环图,就是一棵树)

解题思路:
这是一个无向无环图,也就是一棵树,那么它就肯定有叶子结点,叶子节点的度数为1,此时它相邻点的异或结果实际上就是所求点的编号了。然后把跟叶子节点相邻的点的度数减去1,代表把叶子节点去除,此时异或结果是有变的。需要用本来的异或结果跟该叶子节点再异或一次,就得出除了这个叶子节点外其他点的异或值了,即a^b^c^a=b^c。

代码如下:
#include <cstdio>
#include <queue>
using namespace std;
int in[70000];//存每个点连接的点的个数
int orsum[70000];//存每个点的异或结果
int main()
{
int n;
scanf("%d",&n);
queue<int>que;
pair<int,int>bian[70000];//申请一个存边的数组
for(int i=0;i<n;i++)
{
scanf("%d%d",&in[i],&orsum[i]);
if(in[i]==1)//如果某个点连接的点的个数是1,那么说明它是最下面一层的点,把该点放到队列里面
{
que.push(i);
}
}
int cnt=0;//统计边的个数
while(!que.empty())
{
int from=que.front();
que.pop();
if(in[from]==1)//这个判断,不能少,因为 第一个例子中0的度数在该过程中会变成0
{
int to=orsum[from];
bian[cnt].first=from;
bian[cnt].second=to;
cnt++;
in[from]--;
in[to]--;
orsum[to]=orsum[to]^from;//更新异或结果
if(in[to]==1)
{
que.push(to);
}
}
}
printf("%d\n",cnt);
for(int i=0;i<cnt;i++)
{
printf("%d %d\n",bian[i].first,bian[i].second);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  思维 异或