Submission #300858

#TimeUsernameProblemLanguageResultExecution timeMemory
300858CaroLindaDuathlon (APIO18_duathlon)C++14
100 / 100
227 ms47100 KiB
#include <bits/stdc++.h> #define all(x) x.begin(),x.end() #define debug //printf #define sz(x) (int)(x.size()) #define pii pair<int,int> #define ff first #define ss second #define ll long long using namespace std ; int n , m ; vector<int> height, low , qtdVert , subtree ; vector<ll> toSubtract ; vector< vector<int> > biconnected , tree ; vector<pii> edges ; vector< vector<pii> > adj ; vector<bool> seenEdge , isArt , seenVertex , spun ; ll ans ; // ------------------ GETTING ARTICULATION POINTS AND BICONNECTED COMPONENTS stack<int> st ; void makeComponent(int lastIncluded) { biconnected.push_back( vector<int>() ) ; tree.push_back( vector<int>() ) ; toSubtract.push_back(0LL) ; qtdVert.push_back(0) ; subtree.push_back(0) ; spun.push_back(false) ; while( !st.empty() ) { int onTop = st.top() ; st.pop() ; biconnected.back().push_back( onTop ) ; if(onTop == lastIncluded) return ; } } void lowlink(int x, bool isFirst = false ) { bool hasFwd = false ; seenVertex[x] = true ; for(auto e : adj[x] ) { int target = e.ff ; int id = e.ss ; if( seenEdge[id] ) continue ; st.push( id ) ; seenEdge[id] = true ; if( height[target] != -1 ) { low[x] = min( low[x] , height[target] ) ; continue ; } height[target] = low[target] = height[x] + 1 ; lowlink( target ) ; low[x] = min( low[x] , low[target] ) ; if( (isFirst) ? hasFwd : (low[target] >= height[x]) ) { isArt[x] = true ; makeComponent(id) ; } hasFwd = true ; } } // ----------------------------- void dfsInit(int x, int father ) { subtree[x] = qtdVert[x] ; for(auto neigh : tree[x] ) { if(neigh == father) continue ; dfsInit(neigh, x) ; subtree[x] += subtree[neigh] ; } } long long binomial(ll x) { return ((x-1)*x)/2LL ; } void dfsSpin(int x) { spun[x] = true ; if( x >= n ) { //I'm a component for(int neigh : tree[x] ) toSubtract[x] += binomial( (ll)subtree[neigh] ) ; ans -= toSubtract[x] * (ll)qtdVert[x] ; } for(int neigh : tree[x]) { if( spun[neigh] ) continue ; int mySub = subtree[x] ; int yourSub = subtree[neigh] ; subtree[x] -= subtree[neigh] ; subtree[neigh] = mySub ; dfsSpin(neigh) ; subtree[x] = mySub ; subtree[neigh] = yourSub ; } if( x < n ) { //I'm an articulation point for(int neigh : tree[x]) toSubtract[x] += toSubtract[neigh] - binomial( (ll) subtree[x] - subtree[neigh] ) ; ans -= toSubtract[x] ; } } int main() { scanf("%d%d", &n , &m ) ; adj.resize(n, vector<pii>() ) ; seenEdge.resize(m, false) ; seenVertex.resize(n, false) ; tree.resize(n, vector<int>() ) ; height.resize(n, -1) ; low.resize(n) ; isArt.resize(n, false) ; toSubtract.resize(n, 0LL ) ; qtdVert.resize(n, 1) ; subtree.resize(n, 0) ; spun.resize(n, false) ; for(int i = 0 , a , b ; i < m ; i++ ) { scanf("%d%d", &a, &b ) ; a-- ; b-- ; adj[a].push_back( make_pair(b,i) ) ; adj[b].push_back( make_pair(a,i) ) ; edges.push_back( make_pair(a,b) ) ; } for(int i = 0 ; i < n ; i++ ) { if( seenVertex[i] ) continue ; int toBegin = sz(biconnected) ; height[i] = low[i] = 0 ; lowlink(i, true ) ; makeComponent(-1) ; int toEnd = sz(biconnected) ; for(int j = toBegin ; j < toEnd ; j++ ) { debug("Component %d: " , j ) ; vector<int> nonArt ; for(int e : biconnected[j]) { nonArt.push_back( edges[e].ff ) ; nonArt.push_back( edges[e].ss ) ; debug("(%d %d) and " , edges[e].ff, edges[e].ss ) ; } debug("\n") ; sort(all(nonArt)); nonArt.erase( unique(all(nonArt)) , nonArt.end() ) ; for(int e : nonArt) { if( isArt[e] ) { tree[e].push_back(n + j) ; tree[n+j].push_back(e) ; } else qtdVert[n+j]++ ; } } dfsInit(n+toBegin, -1) ; ans += binomial((ll)subtree[n+toBegin]-1) * (ll)subtree[n+toBegin] ; dfsSpin(n+toBegin) ; } printf("%lld\n" , ans*2LL ) ; }

Compilation message (stderr)

count_triplets.cpp: In function 'int main()':
count_triplets.cpp:197:10: warning: left operand of comma operator has no effect [-Wunused-value]
  197 |    debug("Component %d: " , j ) ;
      |          ^~~~~~~~~~~~~~~~
count_triplets.cpp:205:11: warning: left operand of comma operator has no effect [-Wunused-value]
  205 |     debug("(%d %d) and " , edges[e].ff, edges[e].ss ) ;
      |           ^~~~~~~~~~~~~~
count_triplets.cpp:208:10: warning: statement has no effect [-Wunused-value]
  208 |    debug("\n") ;
      |         ~^~~~~
count_triplets.cpp:155:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  155 |  scanf("%d%d", &n , &m ) ;
      |  ~~~~~^~~~~~~~~~~~~~~~~~
count_triplets.cpp:171:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  171 |   scanf("%d%d", &a, &b ) ;
      |   ~~~~~^~~~~~~~~~~~~~~~~
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...