Submission #351250

#TimeUsernameProblemLanguageResultExecution timeMemory
351250CaroLindaSimurgh (IOI17_simurgh)C++14
100 / 100
226 ms7404 KiB
#include "simurgh.h" #include <bits/stdc++.h> #define debug #define ll long long #define all(x) x.begin(),x.end() #define sz(x) (int)(x.size() ) const int MAXN = 505 ; const int MAXM = MAXN*MAXN ; using namespace std ; int n , m , treeAns ; int U[MAXM] , V[MAXM] , pai[MAXN] ; int cumulativeFoundOnes[MAXN] , lvl[MAXN] , edgeFather[MAXN] ; int edgeStatus[MAXM] ; vector< pair<int,int> > adj[MAXN] ; vector< pair<int,int> > tree[MAXN] ; vector<int> treeIds ; bool vis[MAXN] , isTree[MAXM] ; int find(int x) { if( x == pai[x] ) return x ; return pai[x] = find(pai[x]) ; } bool join(int x, int y ) { x = find(x) ; y = find(y) ; if(x == y ) return false ; if(rand() % 2 ) swap(x,y) ; pai[x] = y ; return true ; } void cleanTime() { for(int i = 0 ; i< n ; i++ ) pai[i] = i ; } int getOther(int edgeId, int knownEnd ) { if( knownEnd == U[edgeId] ) return V[edgeId] ; return U[edgeId] ; } void findTree(int x) { vis[x] = true ; for(auto e : adj[x] ) { int j = e.first ; int id = e.second ; if( vis[j] ) continue ; edgeFather[j] = id ; isTree[id] = true ; treeIds.push_back(id) ; lvl[j] = lvl[x] + 1 ; tree[x].push_back(make_pair(j, id) ) ; findTree(j) ; } } void recalcCumulative(int x) { for(auto e : tree[x] ) { int j = e.first ; int id = e.second ; cumulativeFoundOnes[j] += cumulativeFoundOnes[x] ; if(edgeStatus[id] != -1 ) cumulativeFoundOnes[j]++ ; recalcCumulative(j) ; } } void bb(vector<int> v, int commonRoads ) { if( commonRoads == 0 || sz(v) == 0 ) { for(auto e : v ) edgeStatus[e] = 0 ; return ; } if(sz(v) == commonRoads ) { for(auto e : v ) edgeStatus[e] = 1 ; return ; } vector<int> l , r ; for(int i= 0 ; i < sz(v)/2 ; i++ ) l.push_back(v[i] ) ; for(int i = sz(v)/2 ; i < sz(v) ; i++ ) r.push_back(v[i] ) ; cleanTime() ; vector<int> vec = l ; int c = 0 ; for(auto e : l ) join(U[e] , V[e] ) ; for(auto e : treeIds ) if(join(U[e] , V[e] ) ) { vec.push_back(e) ; c -= edgeStatus[e] ; } c += count_common_roads(vec) ; bb(l, c) ; bb(r, commonRoads - c ) ; } vector<int> find_roads(int N, vector<int> u, vector<int> v) { n = N ; m = sz(u) ; for(int i = 0 ; i < m ; i++ ) { adj[ u[i] ].push_back(make_pair(v[i],i) ) ; adj[ v[i] ].push_back( make_pair(u[i], i) ) ; U[i] = u[i] ; V[i] = v[i] ; edgeStatus[i] = -1 ; } edgeFather[0] = -1 ; findTree(0 ) ; treeAns = count_common_roads( treeIds ) ; for(auto e : treeIds ) debug("%d (which is %d %d) is in tree\n", e, U[e], V[e] ) ; debug("\n") ; for(int i = 0 ; i < m ; i++ ) { if(isTree[i] ) continue ; int up = U[i] , down = V[i] ; if(lvl[up] > lvl[down] ) swap(up,down ) ; if( cumulativeFoundOnes[down] - cumulativeFoundOnes[up] == lvl[down]-lvl[up] ) continue ; vector<int> notFound ; vector<int> alreadyFound ; int x = down ; while( x != up ) { if( edgeStatus[ edgeFather[x] ] == -1 ) notFound.push_back( edgeFather[x] ) ; else alreadyFound.push_back( edgeFather[x] ) ; x = getOther(edgeFather[x] , x ) ; } if( sz(alreadyFound) != 0 ) { vector<int> r(1,i) ; for(int e : treeIds ) if( e != alreadyFound[0] ) r.push_back( e ) ; if( count_common_roads(r) == treeAns-edgeStatus[ alreadyFound[0] ] ) edgeStatus[i] = 0 ; else edgeStatus[i] = 1 ; for(auto e : notFound ) { r.clear() ; for(auto idx : treeIds ) if(idx != e ) r.push_back(idx) ; r.push_back( i ) ; if( treeAns == count_common_roads(r) - edgeStatus[i] ) edgeStatus[e] = 0 ; else edgeStatus[e] = 1 ; } } else { //If I'm golden, as we can't all be golden, then I will increase at least once //If I'm not golden, I can never increase vector<int> ans ; edgeStatus[i] = 0 ; for(auto e : notFound ) { vector<int> r(1,i) ; for(auto idx : treeIds ) if(idx != e ) r.push_back(idx) ; ans.push_back(count_common_roads(r)) ; if( ans.back() == treeAns+1 ) edgeStatus[i] = 1 ; } for(int j = 0 ; j < sz(notFound) ; j++ ) { if( treeAns == ans[j] - edgeStatus[i] ) edgeStatus[ notFound[j] ] = 0 ; else edgeStatus[ notFound[j] ] = 1 ; } } for(int i = 0 ; i< n ; i++ ) cumulativeFoundOnes[i] = 0 ; recalcCumulative(0) ; } for(int e : treeIds ) if(edgeStatus[e] == -1 ) edgeStatus[e] = 1 ; //I know for a fact they are golden (they are bridges) for(auto e : treeIds ) debug("edge %d (%d and %d) is %d\n", e, U[e] , V[e] , edgeStatus[e] ) ; for(int i = 0 ; i < m; i++ ) debug("%d ", edgeStatus[i] ) ; debug("\n") ; for(int i = 0 ; i < n ; i++ ) { vector<int> r ; cleanTime() ; for(auto e : adj[i] ) if( edgeStatus[e.second] == -1 ) { r.push_back(e.second) ; join(i , e.first ) ; } if(sz(r) == 0 ) continue ; int tot = 0 ; for(auto e : treeIds) if( join(U[e] , V[e] ) ) { tot -= edgeStatus[e] ; r.push_back(e) ; } tot += count_common_roads(r) ; while( isTree[ r.back() ] ) r.pop_back() ; bb(r, tot ) ; } vector<int> goldenSet ; for(int i = 0 ; i< m ; i++ ) if(edgeStatus[i] == 1 ) goldenSet.push_back(i) ; return goldenSet ; }

Compilation message (stderr)

simurgh.cpp: In function 'std::vector<int> find_roads(int, std::vector<int>, std::vector<int>)':
simurgh.cpp:155:31: warning: left operand of comma operator has no effect [-Wunused-value]
  155 |  for(auto e : treeIds ) debug("%d (which is %d %d) is in tree\n", e, U[e], V[e] ) ;
      |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
simurgh.cpp:155:73: warning: right operand of comma operator has no effect [-Wunused-value]
  155 |  for(auto e : treeIds ) debug("%d (which is %d %d) is in tree\n", e, U[e], V[e] ) ;
      |                                                                         ^
simurgh.cpp:155:73: warning: right operand of comma operator has no effect [-Wunused-value]
  155 |  for(auto e : treeIds ) debug("%d (which is %d %d) is in tree\n", e, U[e], V[e] ) ;
      |                                                                      ~~~^
simurgh.cpp:156:8: warning: statement has no effect [-Wunused-value]
  156 |  debug("\n") ;
      |       ~^~~~~
simurgh.cpp:251:31: warning: left operand of comma operator has no effect [-Wunused-value]
  251 |  for(auto e : treeIds ) debug("edge %d (%d and %d) is %d\n", e, U[e] , V[e] , edgeStatus[e] ) ;
      |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
simurgh.cpp:251:68: warning: right operand of comma operator has no effect [-Wunused-value]
  251 |  for(auto e : treeIds ) debug("edge %d (%d and %d) is %d\n", e, U[e] , V[e] , edgeStatus[e] ) ;
      |                                                                    ^
simurgh.cpp:251:68: warning: right operand of comma operator has no effect [-Wunused-value]
  251 |  for(auto e : treeIds ) debug("edge %d (%d and %d) is %d\n", e, U[e] , V[e] , edgeStatus[e] ) ;
      |                                                                 ~~~^
simurgh.cpp:251:75: warning: right operand of comma operator has no effect [-Wunused-value]
  251 |  for(auto e : treeIds ) debug("edge %d (%d and %d) is %d\n", e, U[e] , V[e] , edgeStatus[e] ) ;
      |                                                                        ~~~^
simurgh.cpp:252:37: warning: left operand of comma operator has no effect [-Wunused-value]
  252 |  for(int i = 0 ; i < m; i++ ) debug("%d ", edgeStatus[i] ) ;
      |                                     ^~~~~
simurgh.cpp:253:8: warning: statement has no effect [-Wunused-value]
  253 |  debug("\n") ;
      |       ~^~~~~
#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...