# | Submission time | Handle | Problem | Language | Result | Execution time | Memory |
---|---|---|---|---|---|---|---|
981239 | 2024-05-13T02:57:29 Z | Lib | Swapping Cities (APIO20_swap) | C++14 | 0 ms | 0 KB |
#include <bits/stdc++.h> using namespace std; int n,m; vector <vector <int> > InComponents; vector <vector <int> > adj; //the edge list of the KRT vector <int> TVector; int RootID; //ID of the root node of the KRT; struct Edge{ long long Weight; int Start; int End; }; bool operator< (const Edge &x, const Edge &y){ return x.Weight<y.Weight; } Edge Elist[500003]; int Depth[500003]; int Deg[500003]; int CurRep[500003]; //id of the respresentative node on the KRT int Par[500003]; //Parent of node with id i on the KRT; int Toggle[500003]; //is the i-th node on the KRT toggled? int Check[500003]; int Ancestor[500003][20]; long long Val[500003];//the value of the i-th node of the KRT vector <int> KRTID; void DSU(int id, int u, int v, int w){ Deg[u]++; Deg[v]++; //u and v belongs to the same component. The component now has a cycle. Immediately toggle the root node of the current //subtree that includes both u and v on the KRT if(CurRep[u]==CurRep[v]){ //The node isn't toggled just yet. Toggle it immediately if(!Toggle[CurRep[u]]){ Toggle[CurRep[u]]=1; Val[CurRep[u]]=w; }else{ //The node is already toggled by an edge with lower edge. Only a fucking dumbass would touch it - already minimized //toggle value. Just leave it alone } }else{ //u and v doesn't belong to the same component. Merge them int CurID=n-1+id; int OldComp1=CurRep[u], OldComp2=CurRep[v]; adj[CurRep[u]].push_back(CurID); adj[CurRep[v]].push_back(CurID); adj[CurID].push_back(CurRep[u]); adj[CurID].push_back(CurRep[v]); Par[CurRep[u]]=CurID; Par[CurRep[v]]=CurID; if(InComponents[u].size()>InComponents[v].size()){ swap(u,v); //Small to large merging } for(int i=0;i<InComponents[u].size();i++){ InComponents[CurID].push_back(InComponents[u][i]); CurRep[InComponents[u][i]]=CurID; } for(int i=0;i<InComponents[v].size();i++){ InComponents[CurID].push_back(InComponents[v][i]); CurRep[InComponents[v][i]]=CurID; } Val[CurID]=w; //if either of the components are toggled already (having a cycle OR a vertex with degree >3) //OR the merged component has a vertex with degree >3 (either u or v), toggle immediately if(Toggle[OldComp1]||Toggle[OldComp2]||Deg[u]>2||Deg[v]>2){ Toggle[CurID]=1; } KRTID.push_back(CurID); RootID=CurID; } } void init(int N, int M, vector <int> U, vector <int> V, vector <int> W){ n=N; m=M; for(int i=0;i<n+m+5;i++){ InComponents.push_back(TVector); adj.push_back(TVector); } for(int i=1;i<=m;i++){ Elist[i].Weight=W[i-1]; Elist[i].Start=U[i-1]; Elist[i].End=V[i-1]; } sort(Elist+1,Elist+m+1); for(int i=0;i<n;i++){ CurRep[i]=i; InComponents[i].push_back(i); KRTID.push_back(i); } for(int i=1;i<=m;i++){ DSU(i,Elist[i].Start,Elist[i].End,Elist[i].Weight); } //The KRT is now built. BFS from the root node and initialize LCA or something deque <int> dq; dq.push_back(RootID); Check[RootID]=1; int Cur; while(!dq.empty()){ Cur=dq.front(); for(int i=0;i<adj[Cur].size();i++){ if(!Check[adj[Cur][i]]){ dq.push_back(adj[Cur][i]); Check[adj[Cur][i]]=1; Depth[adj[Cur][i]]=Depth[Cur]+1; } } dq.pop_front(); } Par[RootID]=500000; Par[500000]=500000; Toggle[500000]=1; for(int i=0;i<=19;i++){ for(int k=0;k<KRTID.size();k++){ if(i==0){ Ancestor[KRTID[k]][i]=Par[KRTID[k]]; }else{ Ancestor[KRTID[k]][i]=Ancestor[Ancestor[KRTID[k]][i-1]][i-1]; } } } } int getMinimumFuelCapacity(int x, int y){ //I thought that we actually need to use binary lifting to find LCA and then jump from the LCA to find the nearest //toggled node on the KRT //But apparently small-to-large merging ensures that the depth of the tree is always logN or something, so bruteforcing //it is //ok nvm this guy is a fucking moron lmao LogN depth my ass. Wrong analysis, wasted 5 minutes. Fuck me if(Depth[x]<Depth[y]){ swap(x,y); } int JumpLevel=Depth[x]-Depth[y]; for(int i=19;i>=0;i--){ if(JumpLevel >> i & 1){ x=Ancestor[x][i]; } } for(int i=19;i>=0;i--){ if(Ancestor[x][i]!=Ancestor[y][i]){ x=Ancestor[x][i]; y=Ancestor[y][i]; } } x=Par[x]; y=Par[y]; SkipPoint:; int cnt=0; if(Toggle[x]){ return Val[x]; } while(!Toggle[Par[x]]&& Par[x]!=500000){ x=Par[x]; cnt++; } for(int i=19;i>=0;i--){ if(!Toggle[Ancestor[x][i]]){ // x=Ancestor[x][i]; } } x=Par[x]; if(cnt>n+m){ return 1048657;} if(Toggle[x]&&x!=500000){ return Val[x]; } return -1; }