bool propagate() { //fprintf(stderr, "AllDiffDomain::propagate()\n"); // Edmonds-Karp, loop to find and augment a path while (1) { int var; int val; // visit source queue_tail = &queue; for (int i = 0; i < sz; ++i) if (var_nodes[i].match < 0) { *queue_tail = i; queue_tail = &var_nodes[i].next; } *queue_tail = -1; for (int i = 0; i < range; ++i) val_nodes[i].mark = false; // visit vars, also subsume visit of vals while (queue >= 0) { queue_tail = &queue; for (var = queue; var >= 0; var = var_nodes[var].next) for (typename IntView<U>::iterator i = x[var].begin(); i != x[var].end(); ++i) { val = *i; if (!val_nodes[val].mark) { assert(val != var_nodes[var].match); int next_var = val_nodes[val].match; if (next_var < 0) goto augment; val_nodes[val].mark = true; val_nodes[val].next = var; *queue_tail = next_var; queue_tail = &var_nodes[next_var].next; } } *queue_tail = -1; } // no more augmenting paths break; augment: // found an augmenting path while (1) { int parent_val = var_nodes[var].match; val_nodes[val].match = var; var_nodes[var].match = val; if (parent_val < 0) break; val = parent_val; var = val_nodes[val].next; } } //fprintf(stderr, "match"); //for (int i = 0; i < sz; ++i) // fprintf(stderr, " %d", var_nodes[i].match); //fprintf(stderr, "\n"); index = 0; stack = -1; for (int i = 0; i < sz + range; ++i) var_nodes[i].mark = false; for (int i = 0; i < sz; ++i) if (!var_nodes[i].mark && !tarjan(i)) return false; return true; }
int main(){ part = n; for(int i = 1; i <= n; ++i) if(!dfn[i]) tarjan(i, part + 1); }
int main() { freopen("F.in", "r", stdin); scanf("%d", &T); for (int cs = 1; cs <= T; cs++) { scanf("%d%d", &n, &m); nColor = tot = top = nPart = 0; std::fill(h + 1, h + n + m + 1, t = 0); std::fill(dfn + 1, dfn + n + m + 1, 0); std::fill(low + 1, low + n + m + 1, 0); std::fill(cut + 1, cut + n + m + 1, false); for (int i = 1; i <= n; i++) scanf("%d", w + i); for (int i = 1; i <= m; i++) { scanf("%d%d", &r[i].x, &r[i].y); addEdge(r[i].x, r[i].y); } std::fill(belong + 1, belong + n + 1, 0); for (int i = 1; i <= n; i++) { if (belong[i]) continue; static int q[MAXN]; nPart++; int left = 0, right = 0; belong[q[++right] = i] = nPart; while (left < right) { left++; for (int i = h[q[left]]; i; i = e[i].next) { if (belong[e[i].node]) continue; belong[q[++right] = e[i].node] = nPart; } } } std::fill(size + 1, size + n + 1, 0); std::fill(prod + 1, prod + nPart + 1, 1); for (int i = 1; i <= n; i++) { prod[belong[i]] = 1ll * prod[belong[i]] * w[i] % MOD; size[belong[i]]++; } std::fill(h + 1, h + n + m + 1, t = 0); for (int i = 1; i <= m; i++) { addEdge(r[i].x, n + i); addEdge(r[i].y, n + i); } for (int i = 1; i <= n + m; i++) { if (dfn[i]) continue; cut[i] = tarjan(i) > 1; } std::vector<int> dis; for (int i = 1; i <= n + m; i++) { if (i <= n && size[belong[i]] == 1) { col[i] = ++nColor; dis.push_back(col[i]); continue; } if (cut[i]) col[i] = ++nColor; dis.push_back(col[i]); } std::sort(dis.begin(), dis.end()); dis.erase(std::unique(dis.begin(), dis.end()), dis.end()); for (int i = 1; i <= n + m; i++) { col[i] = std::lower_bound(dis.begin(), dis.end(), col[i]) - dis.begin() + 1; } nColor = dis.size(); std::fill(prodBlock + 1, prodBlock + nColor + 1, 1); for (int i = 1; i <= n; i++) { prodBlock[col[i]] = 1ll * prodBlock[col[i]] * w[i] % MOD; } std::fill(h + 1, h + nColor + 1, t = 0); for (int i = 1; i <= m; i++) { if (col[r[i].x] != col[n + i]) { addEdge(col[r[i].x], col[n + i]); //printf("AddEdge(%d, %d)\n", col[r[i].x], col[r[i].y]); } if (col[r[i].y] != col[n + i]) { addEdge(col[r[i].y], col[n + i]); //printf("AddEdge(%d, %d)\n", col[r[i].x], col[r[i].y]); } } int answer = 0, total = 0; for (int i = 1; i <= nPart; i++) { total = (total + prod[i]) % MOD; } std::fill(v + 1, v + nColor + 1, false); for (int i = 1; i <= nColor; i++) { if (v[i]) continue; dfs(i); } for (int i = 1; i <= n; i++) { if (size[belong[i]] == 1) { long long tmp = (total - prod[belong[i]]) % MOD; answer = (answer + 1ll * i * tmp % MOD) % MOD; continue; } if (!cut[i]) { long long tmp = (total - prod[belong[i]]) % MOD; tmp = (tmp + 1ll * prod[belong[i]] * fpm(w[i], MOD - 2) % MOD) % MOD; answer = (answer + 1ll * i * tmp % MOD) % MOD; } else { long long tmp = prod[belong[i]]; tmp = 1ll * tmp * fpm(subProd[col[i]], MOD - 2) % MOD; tmp = (tmp + subSum[col[i]]) % MOD; tmp = (tmp + total - prod[belong[i]]) % MOD; answer = (answer + 1ll * i * tmp % MOD) % MOD; } } answer = (answer % MOD + MOD) % MOD; printf("%d\n", answer); } return 0; }
//求有向图的强联通分量 void find_scc(int n){ dfs_clock = scc_cnt = 0; for(int i = 0;i<n;i++) sccno[i] = pre[i] = 0; for(int i = 0;i<n;i++) if(!pre[i]) tarjan(i); }
std::vector<int> get_bcc(){ for (int i=1;i<=N;i++) if (!chk[i]) tarjan(i); return bcc; }
int main() { /*****/ for(int i = 1;i <= n;i++) if(!dfn[i]) tarjan(i); }
int main(){ while(~scanf("%d %d", &n, &m)){ if(n==0 && m==0) break; init(); while(m--){ int u, v; scanf("%d %d", &u, &v); add(u, v, head, edge); add(v, u, head, edge); } for(int i = 1; i <= n; i++){ if(!dfn[i]) tarjan(i, -1); } cnt = 0; for(int u = 1; u <= n; u++){ for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].v; if(bccno[u] != bccno[v]){ add(bccno[u], v, head1, edge1); } } } d[1] = 0; dfs(1, 1); scanf("%d", &m); while(m--){ int u, v, w; scanf("%d %d %d", &u, &v, &w); int uu = bccno[u], vv = bccno[v], ww = bccno[w]; int uv = lca(uu, vv), uw = lca(uu, ww), vw = lca(vv, ww); if(u==v){ if(u==w) puts("Yes"); else puts("No"); } else if(u==w || v==w) puts("Yes"); else if(uu==vv){ if(uu==ww) puts("Yes"); else puts("No"); } else if(uu==ww){ int ret; if(uv==uu){ vv = swim(vv, ww); ret = judge(vv, u); } else ret = judge(p[uu][0], u); if(ret!=u) puts("Yes"); else puts("No"); } else if(vv==ww){ int ret; if(uv==vv){ uu = swim(uu, ww); ret = judge(uu, v); } else ret = judge(p[vv][0],v); if(ret!=v) puts("Yes"); else puts("No"); } else{ if(uv==uw && vw==ww){ int ret1, ret2; vv = swim(vv, ww); ret1 = judge(vv, w); if(uv==ww){ uu = swim(uu, ww); ret2 = judge(uu, w); } else ret2 = judge(p[ww][0],w); if(ret1!=w && ret2!=w && ret1==ret2) puts("No"); else puts("Yes"); } else if(uv==vw && uw==ww){ int ret1, ret2; uu = swim(uu, ww); ret1 = judge(uu, w); if(uv==ww){ vv = swim(vv, ww); ret2 = judge(vv, w); } else ret2 = judge(p[ww][0],w); if(ret1!=w && ret2!=w && ret1==ret2) puts("No"); else puts("Yes"); } else puts("No"); } } } return 0; }
// merge Strongly Connected Component // return vertex map between old vertex and corresponding new merged vertex void GraphUtil::mergeSCC(Graph& g, int* on, vector<int>& reverse_topo_sort) { vector<int> sn; hash_map< int, pair<int, int> > order; int ind = 0; multimap<int, int> sccmap; // each vertex id correspond with a scc num int scc = 0; int vid; int origsize = g.num_vertices(); // cout << " inside MergeSCC "<< endl; for (int i = 0; i < origsize; i++) { vid = i; if (g[vid].visited) continue; tarjan(g, vid, ind, order, sn, sccmap, scc); } // cout << " inside MergeSCC after tarjan "<< endl; // no component need to merge if (scc == origsize) { for (int i = 0; i < origsize; i++) on[i] = i; // topological sort topological_sort(g, reverse_topo_sort); // update graph's topological id for (int i = 0; i < reverse_topo_sort.size(); i++) g[reverse_topo_sort[i]].topo_id = reverse_topo_sort.size()-i-1; return; } hash_map<int, vector<int> > inlist, outlist; g.extract(inlist, outlist); multimap<int,int>::iterator mit; mit = sccmap.begin(); int num_comp; int maxid = g.num_vertices()-1; while (mit != sccmap.end()) { num_comp = mit->first; if (++sccmap.lower_bound(num_comp) == sccmap.upper_bound(num_comp)) { on[mit->second] = mit->second; ++mit; continue; } maxid++; inlist[maxid] = vector<int>(); outlist[maxid] = vector<int>(); for (; mit != sccmap.upper_bound(num_comp); ++mit) { on[mit->second] = maxid; vector<int> vec = inlist[mit->second]; vector<int>::iterator vit, vit1; vector<int> vec1; bool hasEdge = false; // copy all incoming edges for (vit = vec.begin(); vit != vec.end(); vit++) { hasEdge = false; vec1 = outlist[*vit]; for (vit1 = vec1.begin(); vit1 != vec1.end(); vit1++) { if (*vit1 == maxid) { hasEdge = true; break; } } if (!hasEdge && (*vit != maxid)) { inlist[maxid].push_back(*vit); outlist[*vit].push_back(maxid); } } // copy all outgoing edges vec = outlist[mit->second]; for (vit = vec.begin(); vit != vec.end(); vit++) { hasEdge = false; vec1 = inlist[*vit]; for (vit1 = vec1.begin(); vit1 != vec1.end(); vit1++) if (*vit1 == maxid) { hasEdge = true; break; } if (!hasEdge && (*vit != maxid)) { outlist[maxid].push_back(*vit); inlist[*vit].push_back(maxid); } } // delete old vertex vec = inlist[mit->second]; for (vit = vec.begin(); vit != vec.end(); vit++) { for (vit1 = outlist[*vit].begin(); vit1 != outlist[*vit].end(); ) if (*vit1 == mit->second) outlist[*vit].erase(vit1); else vit1++; } vec = outlist[mit->second]; for (vit = vec.begin(); vit != vec.end(); vit++) { for (vit1 = inlist[*vit].begin(); vit1 != inlist[*vit].end(); ) if (*vit1 == mit->second) inlist[*vit].erase(vit1); else vit1++; } outlist.erase(mit->second); inlist.erase(mit->second); } } g = Graph(inlist, outlist); // topological sort topological_sort(g, reverse_topo_sort); // update graph's topological id for (int i = 0; i < reverse_topo_sort.size(); i++) g[reverse_topo_sort[i]].topo_id = reverse_topo_sort.size()-i-1; // update index map hash_map<int,int> indexmap; hash_map<int, vector<int> >::iterator hit; int k; for (hit = outlist.begin(), k=0; hit != outlist.end(); hit++, k++) { indexmap[hit->first] = k; } for (k = 0; k < origsize; k++) on[k] = indexmap[on[k]]; /* cout << "Index Map" << endl; for (int i = 0; i < origsize; i++) cout << on[i] << " "; cout << endl; cout << "roots: " << g.getRoots().size() << endl; */ }