Submission #673462

#TimeUsernameProblemLanguageResultExecution timeMemory
673462beedleConnecting Supertrees (IOI20_supertrees)C++17
19 / 100
178 ms24076 KiB
#include "supertrees.h"
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <set>
#include <iterator>
#include <stack>
#include <map>
#include <math.h>
#include <bitset>
#include <deque>
#include <string>
#include <tuple>
#include <queue>
#include <numeric>
#include <complex>
#include <assert.h>
#include <unordered_set>
#include <unordered_map>
#define ll long long
#define rep(i, a, b) for (long long i = a; i <= b; i++)
#define endl '\n'
#define all(x) (x).begin (), (x).end ()
#define sz(x) (ll) (x).size ()
using namespace std;

/*
    Disjoint Set Union: Union by rank, size of each component is maintained.

    Usage: dsu(n) -> creates dsu for elements 0 to n-1, with each element as its own component 
           find_set(v) -> as usual 
           union_sets(a,b) -> as usual
           size_containing(v) -> gives size of component containing vertex v
*/

class dsu {
  public:
    vector<int> parent;
    vector<int> size;
    vector<int> rnk;

    dsu(int n) {
        parent.assign(n, 0);
        for (int i = 0; i < n; i++)
            parent[i] = i;
        size.assign(n, 1);
        rnk.assign(n, 0);
    }

    int find_set(int v) {
        if (v == parent[v])
            return v;
        return parent[v] = find_set(parent[v]);
    }

    void union_sets(int a, int b) {
        a = find_set(a);
        b = find_set(b);
        if (a != b) {
            if (rnk[a] < rnk[b])
                swap(a, b);
            parent[b] = a;
            if (rnk[a] == rnk[b])
                rnk[a]++;
            size[a] += size[b];
        }
    }

    int size_containing(int a) { return size[find_set(a)]; }
};

int construct(std::vector<std::vector<int>> p) {
	int n = sz(p);
	std::vector<std::vector<int>> answer;
	for (int i = 0; i < n; i++) {
		std::vector<int> row;
		row.resize(n);
		answer.push_back(row);
	}

	dsu d(n);
	rep(i,0,n-1)
	rep(j,0,n-1)
	if(p[i][j]!=0)
	d.union_sets(i,j);

	rep(i,0,n-1)
	rep(j,0,n-1)
	if(p[i][j]==0 && d.find_set(i)==d.find_set(j))
	return 0;

	rep(i,0,n-1)
	rep(j,0,n-1)
	if(p[i][j]==3)
	return 0;

	vector <int> comps[n];
	rep(i,0,n-1)
	comps[d.find_set(i)].push_back(i);

	rep(compno,0,n-1)
	if(sz(comps[compno])>1)
	{
		dsu ds(n);
		int s=sz(comps[compno]);
		rep(i,0,s-1)
		rep(j,0,s-1)
		{
			int v1=comps[compno][i];
			int v2=comps[compno][j];
			if(p[v1][v2]==1)
			ds.union_sets(v1,v2);
		}
		rep(i,0,s-1)
		rep(j,0,s-1)
		{
			int v1=comps[compno][i];
			int v2=comps[compno][j];
			if(p[v1][v2]==2 && ds.find_set(v1)==ds.find_set(v2))
			return 0;
		}
		vector <int> seqs[n];
		for(auto v:comps[compno])
		seqs[ds.find_set(v)].push_back(v);

		vector <int> cntc;
		rep(i,0,n-1)
		if(sz(seqs[i])>0)
		cntc.push_back(i);

		if(sz(cntc)==2)
		return 0;

		rep(i,0,n-1)
		if(sz(seqs[i])>0)
		for(auto x:seqs[i])
		if(x!=i)
		answer[x][i]=answer[i][x]=1;

		s=sz(cntc);
		rep(i,0,s-2)
		{
			int v1=cntc[i];
			int v2=cntc[i+1];
			answer[v1][v2]=answer[v2][v1]=1;
		}
		int v1=cntc[0];
		int v2=cntc[s-1];
		answer[v1][v2]=answer[v2][v1]=1;
	}

	build(answer);
	return 1;
}


// signed main() 
// {
// 	vector <vector<int>> p={{1,1,2,2},{1,1,2,2},{2,2,1,2},{2,2,2,1}};
// 	construct(p);
// 	return 0;
// }
#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...