Light OJ - 1168 Tutorial

Problem Description here

Prerequisite of this problem DFSStrongly Connected Component(SCC)


Problem:

সহজ ভাষায় বলতে গেলে এই প্রব্লেমে মূলত বলা হয়েছে, আমাকে অনেকগুলো এজ দেয়া থাকবে। ০ নোড থেকে যাত্রা শুরু করে সবগুলো এজ এক্সেক্টলি ১ বার ভিজিট করা সম্ভব কি না বের করতে হবে। 


Solution:

১) SCC সম্পর্কে ধারণা থাকলে এবং একটু চিন্তা করলেই দেখবে যে, SCC এর যেকোন নোড থেকে যাত্রা শুরু করে সবগুলো এজ এক্সেক্টলি ১বার ভিজিট করা সম্ভব। 

২) তাহলে, এই প্রব্লেমে আমার প্রথম কাজ হচ্ছে, গ্রাফটিকে অনেকগুলো SCC তে ভাগ করা। এখন, প্রতিটি কম্পোনেন্টকে একটি নোড কল্পনা করলে দেখবে যে একটি DAG(Directed Acyclic Graph) তৈরী হয়। 

৩) এখন, নতুন এই DAG এর জন্য আমাকে দেখতে হবে ০ নোড থেকে যাত্রা শুরু করে সবগুলো এজ এক্সেক্টলি ১বার ভিজিট করা যায় কি না? অর্থাৎ, আমাকে দেখতে হবে যে DAG এর প্রতিটি নোডের Child সর্বোচ্চ একটির মধ্যে সীমাবদ্ধ কি না এবং ০ থেকে যাত্রা শুরু করে সকল নোড ভিজিট করা যায় কি না। 

আশা করি এখন প্রব্লেমটি নিজে নিজেই সলভ করা সম্ভব।

তাও ব্যার্থ হলে কোড দেখতে পারোঃ 

#include<bits/stdc++.h>
#define ll long long int
#define pii pair<int,int>
#define sc scanf
#define scin(x) sc("%d",&(x))
#define scin2(x,y) sc("%d %d",&(x),&(y))
#define pf printf
#define ms(a,b) memset(a,b,sizeof(a))
#define pb(a) push_back(a)
#define vi vector<int>
#define RUN_CASE(t,T) for(__typeof(t) t=1;t<=T;t++)
using namespace std;
#define sz 1009
set<int>nodes;
map<int , int>compress;
vector<pii>edges;
vi graph[sz],rgraph[sz],comp[sz],dag[sz];
stack<int>stk;
int ans=1,vis[sz];
void Clean()
{
ans = 1;
nodes.clear();
edges.clear();
compress.clear();
while(!stk.empty())
stk.pop();
for(int i=0 ; i<sz ; i++){
vis[i] = 0;
graph[i].clear();
rgraph[i].clear();
comp[i].clear();
dag[i].clear();
}
}
void DFS1(int u)
{
vis[u] = 1;
for(auto v : graph[u]){
if(!vis[v])
DFS1(v);
}
stk.push(u);
}
void DFS2(int u,int compno)
{
vis[u] = compno;
comp[compno].pb(u);
for(auto v : rgraph[u]){
if(!vis[v])
DFS2(v , compno);
}
}
void DFS(int u)
{
vis[u] = 1;
if((int)dag[u].size() > 1){
ans = 0;
return;
}
for(auto v : dag[u]){
if(!vis[v])
DFS(v);
}
}
void Solve(int t)
{
int i,j,k,n,u,v,wish,src=-1,cnt=0;
scin(n);
nodes.insert(0);
for(i=1 ; i<=n ; i++){
scin(wish);
for(j=1 ; j<=wish ; j++){
scin2(u , v);
edges.pb(make_pair(u , v));
nodes.insert(u);
nodes.insert(v);
}
}
///
for(auto x : nodes){
compress[x] = ++cnt;
}
for(auto pr : edges){
u = compress[pr.first];
v = compress[pr.second];
graph[u].pb(v);
rgraph[v].pb(u);
}
///SCC Call
for(i=1 ; i<=cnt ; i++){
if(!vis[i])
DFS1(i);
}
int compno = 0;
ms(vis , 0);
while(!stk.empty()){
int top = stk.top();
stk.pop();
if(!vis[top])
DFS2(top , ++compno);
}
///Make DAG according to SCC
for(u=1 ; u<=cnt ; u++){
int nu = vis[u];
for(auto adj : graph[u]){
int nv = vis[adj];
if(nu == nv)
continue;
dag[nu].pb(nv);
}
}
src = vis[1]; ///Initially, the snake is at checkpoint 0 which is compressed to node 1. And node 1 is at node vis[1] in DAG
ms(vis , 0);
DFS(src);
for(i=1 ; i<=compno ; i++)
ans &= vis[i];
if(ans)
pf("Case %d: YES\n",t);
else
pf("Case %d: NO\n",t);
Clean();
}
int main()
{
int t,T;
scin(T);
RUN_CASE(t,T)
{
Solve(t);
}
return 0;
}
/** Stuff u should look for
* Avoid overflow
* Corner(Small) case
* Don't get stuck on one approach
* Don't forget to clean used memory in each case
**/
view raw LOJ - 1168.cpp hosted with ❤ by GitHub

Happy Coding 😊

Comments

Trending Post

At Coder Educational DP-A | DP Series(Episode-1)

STL পরিচিতি । পর্ব - ০১