4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: //------------------------------------------------------------- 4fd800b3a8 2011-02-23 kinaba: // Gomory-Hu 4fd800b3a8 2011-02-23 kinaba: // All Pair Minimum Cuts for an Undirected Graph 4fd800b3a8 2011-02-23 kinaba: // O(V^4) 4fd800b3a8 2011-02-23 kinaba: // 4fd800b3a8 2011-02-23 kinaba: // G : undirected (G[i].has(j) <==> G[j].has(i)) 4fd800b3a8 2011-02-23 kinaba: // F : flow-capacity F[i][j] = F[j][i] = Capacity 4fd800b3a8 2011-02-23 kinaba: // 4fd800b3a8 2011-02-23 kinaba: // Verified by 4fd800b3a8 2011-02-23 kinaba: // - CodeCraft 09 CUTS 4fd800b3a8 2011-02-23 kinaba: //------------------------------------------------------------- 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: static const int NV = 512; 4fd800b3a8 2011-02-23 kinaba: typedef int flow; 4fd800b3a8 2011-02-23 kinaba: typedef int vert; 4fd800b3a8 2011-02-23 kinaba: typedef vert edge; 4fd800b3a8 2011-02-23 kinaba: typedef vector<edge> edges; 4fd800b3a8 2011-02-23 kinaba: typedef vector<edges> graph; 4fd800b3a8 2011-02-23 kinaba: typedef flow flow_graph[NV][NV]; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: flow_graph GHF; 4fd800b3a8 2011-02-23 kinaba: void GomoryHu( graph& G, flow_graph F, flow_graph AllPairMinCut ) 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: int N = G.size(); 4fd800b3a8 2011-02-23 kinaba: vector<vert> parent(N, 0); 4fd800b3a8 2011-02-23 kinaba: vector<flow> weight(N, 0); 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: // construct the Gomory-Hu Tree 4fd800b3a8 2011-02-23 kinaba: for(vert s=1; s<N; ++s) 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: vert t = parent[s]; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: // mincut between s and t 4fd800b3a8 2011-02-23 kinaba: memcpy(GHF, F, sizeof(GHF)); 4fd800b3a8 2011-02-23 kinaba: flow mincut = 0; 4fd800b3a8 2011-02-23 kinaba: for(;;) { 4fd800b3a8 2011-02-23 kinaba: // bfs 4fd800b3a8 2011-02-23 kinaba: vector<vert> prev(N, -1); prev[s]=s; 4fd800b3a8 2011-02-23 kinaba: queue<vert> Q; Q.push(s); 4fd800b3a8 2011-02-23 kinaba: while( !Q.empty() ) { 4fd800b3a8 2011-02-23 kinaba: vert v = Q.front(); Q.pop(); 4fd800b3a8 2011-02-23 kinaba: for(int i=0; i<G[v].size(); ++i) { 4fd800b3a8 2011-02-23 kinaba: vert u = G[v][i]; 4fd800b3a8 2011-02-23 kinaba: if( prev[u]==-1 && GHF[v][u] ) 4fd800b3a8 2011-02-23 kinaba: prev[u]=v, Q.push(u); 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: if( prev[t] == -1 ) 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: // done: separeted to {v|prev[v]!=-1} and {v|prev[v]==-1} 4fd800b3a8 2011-02-23 kinaba: // split t's children 4fd800b3a8 2011-02-23 kinaba: weight[s] = mincut; 4fd800b3a8 2011-02-23 kinaba: for(vert v=0; v<N; ++v) 4fd800b3a8 2011-02-23 kinaba: if( parent[v]==t && prev[v]!=-1 && v!=s ) 4fd800b3a8 2011-02-23 kinaba: parent[v] = s; 4fd800b3a8 2011-02-23 kinaba: vert pt = parent[t]; 4fd800b3a8 2011-02-23 kinaba: if( prev[pt]!=-1 ) 4fd800b3a8 2011-02-23 kinaba: parent[s]=pt, parent[t]=s, weight[s]=weight[t], weight[t]=mincut; 4fd800b3a8 2011-02-23 kinaba: break; 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: // flow... 4fd800b3a8 2011-02-23 kinaba: flow cur = 0x7fffffff; 4fd800b3a8 2011-02-23 kinaba: for(vert v=t; v!=s; v=prev[v]) 4fd800b3a8 2011-02-23 kinaba: cur = min(cur, GHF[prev[v]][v]); 4fd800b3a8 2011-02-23 kinaba: for(vert v=t; v!=s; v=prev[v]) 4fd800b3a8 2011-02-23 kinaba: GHF[prev[v]][v] -= cur, GHF[v][prev[v]] += cur; 4fd800b3a8 2011-02-23 kinaba: mincut += cur; 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: // AllPairMinCuts over the G-H tree 4fd800b3a8 2011-02-23 kinaba: for(vert s=0; s<N; ++s) { 4fd800b3a8 2011-02-23 kinaba: vector<vert> ps_s; 4fd800b3a8 2011-02-23 kinaba: for(vert v=s ;; v=parent[v]) 4fd800b3a8 2011-02-23 kinaba: { ps_s.push_back(v); if( v==parent[v] ) break; } 4fd800b3a8 2011-02-23 kinaba: reverse(ps_s.begin(), ps_s.end()); 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: for(vert t=s+1; t<N; ++t) { 4fd800b3a8 2011-02-23 kinaba: vector<vert> ps_t; 4fd800b3a8 2011-02-23 kinaba: for(vert v=t ;; v=parent[v]) 4fd800b3a8 2011-02-23 kinaba: { ps_t.push_back(v); if( v==parent[v] ) break; } 4fd800b3a8 2011-02-23 kinaba: reverse(ps_t.begin(), ps_t.end()); 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: vert ca; 4fd800b3a8 2011-02-23 kinaba: for(int i=0; i<ps_s.size() && i<ps_t.size() && ps_s[i]==ps_t[i]; ++i) 4fd800b3a8 2011-02-23 kinaba: ca = ps_s[i]; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: flow s_to_root = 0x7fffffff, t_to_root = 0x7fffffff; 4fd800b3a8 2011-02-23 kinaba: for(vert v=s; v!=ca; v=parent[v]) 4fd800b3a8 2011-02-23 kinaba: s_to_root = min(s_to_root, weight[v]); 4fd800b3a8 2011-02-23 kinaba: for(vert v=t; v!=ca; v=parent[v]) 4fd800b3a8 2011-02-23 kinaba: t_to_root = min(t_to_root, weight[v]); 4fd800b3a8 2011-02-23 kinaba: AllPairMinCut[s][t] = AllPairMinCut[t][s] = min(s_to_root, t_to_root); 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: }