A tree is given with N nodes and N-1 edges, and the edges are deleted in some order. After each deletion, you need to give the number of nodes on present in each of the two newly created nodes.
Note: the root is unknown; N<=300000; For Example: A tree is given with the 6 nodes numbered from 1 to 6 with following edges :
edge 1 >> 1 - 2
edge 2 >> 2 - 3
edge 3 >> 1 - 4
edge 4 >> 4 - 5
edge 5 >> 4 - 6
Now we have a permutation of 1 to n-1 integers which denotes the order in which > the edges will get deleted. So suppose we have permutation as: 4 3 1 2 5, Tree is:
The output will be in the following form :
When edge 4 will get deleted : no of nodes will get split as : 1 and 5
When the edge 3 will get delete the no of nodes will split in 2 and 3 (note that the node 5 is already deleted)
Similarly for later edges the output should be:
- For edge 1 : 1 and 2
- Then edge 2 : 1 and 1
- Then edge 5 : 1 and 1
My approach is I am creating a component array and by performing BFS upon one side of the edge within same component, and updating the component to new value and counting nodes. and if total nodes in component is X and count is y and print the ans as y and X-y.
This is O(N2) approach. I need a better solution which can give me the ans in N * log(N) .
any other approach anyone can guide me about. It will be helpful.
My Source Code is :
EdgeDeletion.class
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
public class EdgeDeletion {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
Reader s=new Reader();
int n = s.nextInt();
Edge[] edges = new Edge[n];
Graph G = new Graph(n);
for(int i = 1 ;i<n;i++)
{
int a =s.nextInt();
int b = s.nextInt();
G.addEdge(a, b);
edges[i] = new Edge(a, b);
}
int component[] = new int[n+1];
int sizeComp[] = new int[n+1];
Arrays.fill(component,1);
sizeComp[1] = n;
int D[] = new int[n];
for(int i = 1;i<n;i++)
{
D[i] = s.nextInt();
}
for(int i = 1 ;i<n;i++)
{
int a = edges[D[i]].a;
int b = edges[D[i]].b;
long ans = 0;
int c = component[a];
boolean[] v = new boolean[n+1];
v[b] = true;
Queue<Integer> queue = new LinkedList<>();
queue.add(a);
int size = 0;
while(!queue.isEmpty())
{
int k = queue.poll();
v[k] = true;
size++;
component[k] = i+1;
for(int no : G.adj[k])
{
if(!v[no]&&component[no]==c)
{
queue.add(no);
}
}
}
int size_prev = sizeComp[c];
sizeComp[c] = sizeComp[c] - size;
sizeComp[i+1] = size;
bw.write(Math.min(size,sizeComp[c])+" "+Math.Max(size,sizeComp[c])+\n");
}
bw.flush();
}
}
Graph.java
class Graph {
public int v;
public List<Integer> adj[];
public int degree[];
public Graph(int v) {
this.v = v;
adj = new ArrayList[v + 1];
degree = new int[v + 1];
for (int i = 1; i <= v; i++) {
adj[i] = new ArrayList<Integer>();
}
}
public void addEdge(int v, int w) {
adj[v].add(w);
adj[w].add(v);
degree[v]++;
degree[w]++;
}
public int findRootForMinHieght() {
Queue<Integer> que = new LinkedList<Integer>();
int x = v;
for (int i = 1; i <= this.v; i++) {
if (degree[i] == 1)
que.add(i);
}
while (x > 2) {
int t = que.poll();
x--;
for (int k : adj[t]) {
degree[k]--;
if (degree[k] == 1)
que.add(k);
}
}
while (que.size() > 1) {
que.poll();
}
return que.poll();
}
}
node.java
class node {
int parent;
int r;
HashSet<Integer> child;
public node(int parent) {
this.parent = parent;
child = new HashSet<>();
}
}
Edge.class
class Edge {
int a;
int b;
public Edge(int a, int b) {
this.a = a;
this.b = b;
}
}
Reader.java
class Reader {
final private int BUFFER_SIZE = 1 << 16;
private DataInputStream din;
private byte[] buffer;
private int bufferPointer, bytesRead;
public Reader() {
din = new DataInputStream(System.in);
buffer = new byte[BUFFER_SIZE];
bufferPointer = bytesRead = 0;
}
public Reader(String file_name) throws IOException {
din = new DataInputStream(new FileInputStream(file_name));
buffer = new byte[BUFFER_SIZE];
bufferPointer = bytesRead = 0;
}
public String readLine() throws IOException {
byte[] buf = new byte[64]; // line length
int cnt = 0, c;
while ((c = read()) != -1) {
if (c == '\n')
break;
buf[cnt++] = (byte) c;
}
return new String(buf, 0, cnt);
}
public int nextInt() throws IOException {
int ret = 0;
byte c = read();
while (c <= ' ')
c = read();
boolean neg = (c == '-');
if (neg)
c = read();
do {
ret = ret * 10 + c - '0';
} while ((c = read()) >= '0' && c <= '9');
if (neg)
return -ret;
return ret;
}
public long nextLong() throws IOException {
long ret = 0;
byte c = read();
while (c <= ' ')
c = read();
boolean neg = (c == '-');
if (neg)
c = read();
do {
ret = ret * 10 + c - '0';
} while ((c = read()) >= '0' && c <= '9');
if (neg)
return -ret;
return ret;
}
public double nextDouble() throws IOException {
double ret = 0, div = 1;
byte c = read();
while (c <= ' ')
c = read();
boolean neg = (c == '-');
if (neg)
c = read();
do {
ret = ret * 10 + c - '0';
} while ((c = read()) >= '0' && c <= '9');
if (c == '.') {
while ((c = read()) >= '0' && c <= '9') {
ret += (c - '0') / (div *= 10);
}
}
if (neg)
return -ret;
return ret;
}
private void fillBuffer() throws IOException {
bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
if (bytesRead == -1)
buffer[0] = -1;
}
private byte read() throws IOException {
if (bufferPointer == bytesRead)
fillBuffer();
return buffer[bufferPointer++];
}
public void close() throws IOException {
if (din == null)
return;
din.close();
}
}