Submission #1353492

#TimeUsernameProblemLanguageResultExecution timeMemory
1353492nikulid슈퍼트리 잇기 (IOI20_supertrees)C++20
19 / 100
71 ms22088 KiB
#include "supertrees.h"
#include <vector>

using namespace std;

#include <iostream>
bool debug=0;
#define dout if(debug)cout<<"# "

vector<int> head, tsize;
vector<vector<int>> answer;

void conn(int u, int v){
  answer[u][v]=1;
  answer[v][u]=1;
}
void disconn(int u, int v){
  answer[u][v]=0;
  answer[v][u]=0;
}

int query(int u){
  // find the representative of u
  if(head[u]==u)return u;
  return head[u]=query(head[u]);
}

void do_union(int u, int v){ // union by size :)
  if(query(u)==query(v))return;
  if(tsize[query(v)] > tsize[query(u)]){
    // add u to v
    tsize[query(v)] += tsize[query(u)];
    tsize[query(u)] = 0;
    head[query(u)] = query(v);
  } else{
    // add v to u
    tsize[query(u)] += tsize[query(v)];
    tsize[query(v)] = 0;
    head[query(v)] = query(u);
  }
}

int construct(vector<vector<int>> p) {
	int n = p.size();
  // assume test case 3.

  // initiate tsize and head
  tsize = vector<int>(n, 1);
  head = vector<int>(n);
  for(int i=0; i<n; i++){
    head[i]=i;
  }

  for(int y=0; y<n; y++){
    for(int x=0; x<n; x++){
      if(p[y][x]==2){
        do_union(y,x);
      }
    }
  }
  dout<<"debug, size:\n";
  for(int i=0; i<n; i++){
    dout<<tsize[i]<<" ";
  }dout<<"\n";
  dout<<"debug, head:\n";
  for(int i=0; i<n; i++){
    dout<<head[i]<<" ";
  }dout<<"\n";
  dout<<"debug, query:\n";
  for(int i=0; i<n; i++){
    dout<<query(i)<<" ";
  }dout<<"\n";
  // now go over everything again, and check if 2 unioned nodes have to be seperate. In this case, we return 0.
  for(int y=0; y<n; y++){
    if(head[y]==y && tsize[y] == 2){
      // impossible to have a ring of size 2
      dout<<"ring "<<y<<" has size 2, which is impossible.\n";
      return 0;
    }
    for(int x=0; x<n; x++){
      if(p[y][x] == 0 && query(y)==query(x)){
        dout<<"no solution exists, because: \n";
        dout<<"p["<<y<<"]["<<x<<"] = " << p[y][x]<<" = 0, and query("<<y<<")="<<query(y)<<" == query("<<x<<")="<<query(x)<<"\n";
        return 0;
      }
    }
  }
  vector<int> last(n);
  for(int i=0; i<n; i++){
    last[i] = i;
  }

  // now we know there exists a construction which meets the requirements
  dout<<"there exists a valid solution.\n";
  answer = vector<vector<int>>(n, vector<int>(n,0));
  int chead;
  vector<int> ncon(n,0);
  for(int i=0; i<n; i++){
    chead = query(i);
    if(chead == i){
      // this is the representative of a ring, or a lone node.
      // last[chead] = chead;
      continue;
    } else{
      // this is a part of a ring, and not the representative.
      if(last[chead] != chead && ncon[last[chead]] > 1){
        // insert into the ring normally
        dout<<i<<" is begin inserted normally to ring "<<chead<<"\n";
        disconn(last[chead], chead);
        conn(last[chead], i);
        conn(chead, i);
        last[chead] = i;
        ncon[i] = 2;
      } else if(last[chead] == chead){
        // 2nd node in the ring
        dout<<i<<" is the 2nd node of ring "<<chead<<".\n";
        ncon[i] = 1;
        conn(i,chead);
        last[chead] = i;
      } else if(ncon[last[chead]] == 1){
        // 3rd node in the ring: insert without disconnecting the previous ones.
        dout<<i<<" is the 3rd node of ring "<<chead<<".\n";
        ncon[i] = 2;
        ncon[last[chead]] = 2;
        conn(i,chead);
        conn(i,last[chead]);
        last[chead] = i;
      }
    }
  }
  build(answer);
	return 1;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...