Submission #1160040

#TimeUsernameProblemLanguageResultExecution timeMemory
1160040jer033Village (BOI20_village)C++20
100 / 100
193 ms31516 KiB
#include <iostream> #include <map> #include <utility> #include <vector> #include <algorithm> #include <string> #include <stack> using namespace std; using ll = long long; const ll INF = 1000000; ll permutation[11]; void nextpermu(ll n) { ll swapa = n-1; while (permutation[swapa]>permutation[swapa+1]) { swapa--; } ll swapb=swapa+1; for (ll i=swapa+1; i<=n; i++) { if (permutation[i]>permutation[swapa]) { swapb=i; } } ll swapper = permutation[swapa]; permutation[swapa]=permutation[swapb]; permutation[swapb]=swapper; sort(permutation+swapa+1, permutation+n+1); } ll distanc[11][11]; ll visited[100005]; ll visitlist[100005]; void bfs(ll root, vector< vector<ll> > edgelist) { ll currindex = 0; ll totalvisited = 1; for (ll i=0; i<=11; i++) { visited[i]=0; visitlist[i]=0; } visited[root]=1; visitlist[1]=root; while (currindex<totalvisited) { currindex++; ll currnode = visitlist[currindex]; for (ll neigh: edgelist[currnode]) { if (visited[neigh]==0) { totalvisited++; visitlist[totalvisited]=neigh; visited[neigh]=visited[currnode]+1; distanc[root][neigh]=visited[currnode]; } } } } ll hipermu[11]; ll lopermu[11]; void solvesubtask1(ll n, vector< vector<ll> > edgelist) { hipermu[0]=0; lopermu[0]=INF; for (ll i=1; i<=n; i++) { bfs(i, edgelist); } while (permutation[1]>=1) { bool derangement = 1; for (ll i=1; i<=n; i++) { if (permutation[i]==i) derangement = 0; } if (derangement) { ll score = 0; for (ll i=1; i<=n; i++) { score = score + distanc[i][permutation[i]]; } if (score<lopermu[0]) { lopermu[0]=score; for (ll i=1; i<=n; i++) { lopermu[i]=permutation[i]; } } if (score>hipermu[0]) { hipermu[0]=score; for (ll i=1; i<=n; i++) { hipermu[i]=permutation[i]; } } } nextpermu(n); } } ll parent[100005]; ll subtreesize[100005]; ll centroidfinder(ll n, ll root, vector< vector<ll> > edgelist) { //copy of bfs ll currindex = 0; ll totalvisited = 1; visited[root]=1; visitlist[1]=root; parent[root]=0; while (currindex<totalvisited) { currindex++; ll currnode = visitlist[currindex]; for (ll neigh: edgelist[currnode]) { if (visited[neigh]==0) { totalvisited++; visitlist[totalvisited]=neigh; visited[neigh]=visited[currnode]+1; parent[neigh]=currnode; } } } for (ll i=n; i>=1; i--) { ll currnode = visitlist[i]; subtreesize[currnode]++; if ((2*subtreesize[currnode])>=n) return currnode; ll myparent = parent[currnode]; subtreesize[myparent]+=subtreesize[currnode]; } return -1;//should not happen } void centroidbfs(ll n, ll centroid, vector< vector<ll> > edgelist) { ll currindex = 0; ll totalvisited = 0; for (ll i=1; i<=n; i++) { visited[i]=0; visitlist[i]=0; parent[i]=0; subtreesize[i]=0; } visited[centroid]=1;//we dont want it to go to centroid parent[centroid]=0; //dfs one level then bfs the rest for (ll child: edgelist[centroid]) { //each time the loop runs, it starts and ends with currindex = totalvisited parent[child]=centroid; totalvisited++; visited[child]=1; visitlist[totalvisited]=child; while (currindex<totalvisited) { currindex++; ll currnode = visitlist[currindex]; for (ll neigh: edgelist[currnode]) { if (visited[neigh]==0) { totalvisited++; visitlist[totalvisited]=neigh; visited[neigh]=1; parent[neigh]=currnode; } } } } visitlist[0]=centroid; for (ll i=n-1; i>=1; i--) { ll currnode = visitlist[i]; subtreesize[currnode]++; ll myparent = parent[currnode]; subtreesize[myparent]+=subtreesize[currnode]; } subtreesize[centroid]=0;//obviously not true but it allows us to skip the centroid later in the calculation } long long largest = 0; ll finalanswer[100005]; void solvelargest(ll n, vector< vector<ll> > edgelist) { ll acentroid = centroidfinder(n, 1, edgelist); centroidbfs(n, acentroid, edgelist); for (ll i=1; i<=n; i++) { long long trsize = subtreesize[i]; largest += trsize; } largest = largest*2; for (ll i=0; i<=n-1; i++) { ll start = visitlist[i]; ll endindex = (i+(n/2))%n; ll end = visitlist[endindex]; finalanswer[start]=end; } } ll dp[100005][2]; //dp[i][0] is the answer for itself //dp[i][1] is the answer for its children combined bool carefor[100005]; //INF has been defined as 1M ll small[100005]; ll total; void vertexcover(ll n, ll root, vector< vector<ll> > edgelist) { //copy of bfs //cout << "VERTEX COVER STARTED\n"; for (ll i=1; i<=n; i++) { visited[i]=0; visitlist[i]=0; parent[i]=0; } ll currindex = 0; ll totalvisited = 1; visited[root]=1; visitlist[1]=root; parent[root]=0; vector< vector<ll> > children; children.resize(n+1); while (currindex<totalvisited) { currindex++; ll currnode = visitlist[currindex]; for (ll neigh: edgelist[currnode]) { if (visited[neigh]==0) { totalvisited++; visitlist[totalvisited]=neigh; visited[neigh]=visited[currnode]+1; parent[neigh]=currnode; children[currnode].push_back(neigh); } } } //cout << "BFS DONE\n"; for (ll i=n; i>=1; i--) { ll currnode = visitlist[i]; ll ansa = 0; ll ansb = 0; ll childrentaken = 0; for (ll child: children[currnode]) { ansb+=dp[child][0]; if (dp[child][0] >= (dp[child][1]+1)) { childrentaken++; ansa += (dp[child][1]+1); } else { ansa += dp[child][0]; } } if (children[currnode].size()==0) { ansa = INF; } else if (childrentaken == 0) { ansa++; } dp[currnode][0] = ansa; dp[currnode][1] = ansb; //cout << i << ' ' << currnode << ' ' << ansa << ' ' << ansb << '\n'; } //cout << "DP DONE\n"; vector< vector<ll> > newedgelist; newedgelist.resize(n+3); carefor[root]=1; for (ll i=1; i<=n; i++) { carefor[i]=1; } for (ll i=1; i<=n; i++) { ll currnode = visitlist[i]; //cout << currnode << '\n'; if (carefor[currnode]) { //cout << "I CARE FOR THIS\n"; ll edgestaken = 0; for (ll child: children[currnode]) { //cout << "I HAVE A CHILD, IT IS " << child << '\n'; if (dp[child][0] >= (dp[child][1]+1)) { edgestaken++; newedgelist[currnode].push_back(child); newedgelist[child].push_back(currnode); //cout << "EDGE BETWEEN " << currnode << " AND " << child << '\n'; carefor[child]=0; } } //cout << "YES YES YES\n"; if (edgestaken==0 and children[currnode].size()>0) { ll child = children[currnode][0]; carefor[child]=0; //MAYBE THIS IS THE ERROR for (ll grandchild: children[child]) { carefor[grandchild]=1; } newedgelist[currnode].push_back(child); newedgelist[child].push_back(currnode); //cout << "EDGE BETWEEN " << currnode << " AND " << child << '\n'; } //cout << "THIS IS DONE\n"; } if (children[currnode].size()==0 and newedgelist[currnode].size()==0) { ll myparent = parent[currnode]; newedgelist[currnode].push_back(myparent); newedgelist[myparent].push_back(currnode); } } //cout << "NEWEDGELIST COMPLETE\n"; for (ll i=1; i<=n; i++) { visited[i]=0; visitlist[i]=0; parent[i]=0; } //implement dfs total = 2*n; ll check = 1; while (check<=n) { if (visited[check]==0) { total--; total--; stack< vector<ll> > tovisit; ll prev = check; ll childcount = newedgelist[check].size(); vector<ll> childs; childs.push_back(childcount); for (ll i=0; i<childcount; i++) { childs.push_back(newedgelist[check][i]); } visited[check]=1; tovisit.push(childs); while (not tovisit.empty()) { ll topsize = tovisit.top()[0]; if (topsize==0) { tovisit.pop(); } else { ll nextchild = tovisit.top()[topsize]; tovisit.top()[0]--; if (visited[nextchild]==0) { visited[nextchild]=1; small[prev]=nextchild; prev=nextchild; ll childcountt = newedgelist[nextchild].size(); vector<ll> childss; childss.push_back(childcountt); for (ll i=0; i<childcountt; i++) { childss.push_back(newedgelist[nextchild][i]); } tovisit.push(childss); } } } small[prev]=check; } check++; } //cout << "DFS DONE AND PROCESS DONE\n"; } int main() { ll n; cin >> n; vector< vector<ll> > edgelist; edgelist.resize(n+1); for (ll edge=1; edge<=(n-1); edge++) { ll a, b; cin >> a >> b; edgelist[a].push_back(b); edgelist[b].push_back(a); } if (n<=0) { for (ll i=0; i<=n; i++) { permutation[i]=i; } solvesubtask1(n, edgelist); cout << lopermu[0] << ' ' << hipermu[0] << '\n'; for (ll i=1; i<=n; i++) { cout << lopermu[i]; if (i==n) { cout << '\n'; } else { cout << ' '; } } for (ll i=1; i<=n; i++) { cout << hipermu[i]; if (i==n) { cout << '\n'; } else { cout << ' '; } } } else { solvelargest(n, edgelist); vertexcover(n, 1, edgelist); cout << total << ' ' << largest << '\n'; for (ll i=1; i<=n; i++) { cout << small[i]; if (i==n) { cout << '\n'; } else { cout << ' '; } } for (ll i=1; i<=n; i++) { cout << finalanswer[i]; if (i==n) { cout << '\n'; } else { cout << ' '; } } } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...