// Author: Lech Duraj // O(mn + q log^2 n), bfs + persistent segment tree #include #include #include #include using namespace std; //#define dprintf(...) fprintf(stderr,__VA_ARGS__) #define dprintf(...) const int infty = 1e9+1; typedef pair PII; struct edge_type { int a, b, w; }; bool operator<(edge_type e, edge_type f) { return e.w < f.w; } vector edge; vector< vector > spanning; vector< vector > stree; int M; void tree_init(int m) { stree.clear(); M = 1; while(M0) { int w = stree[2*x].back().second+stree[2*x+1].back().second; if (stree[x].back().first==s) stree[x].pop_back(); stree[x].push_back(PII(s,w)); x = x/2; } } int sum(int s, int q) { dprintf("Version %d, at most %d.\n",s,q); q += M; int res = 0; while(q>1) { dprintf("Node %d\n",q); if (q%2==1) { q--; dprintf("Taking node %d.\n",q); res += (upper_bound(stree[q].begin(),stree[q].end(),PII(s,-infty),greater())-1)->second; } q /= 2; } return res; } int heaviest(int x, int p, int goal) { int j = -infty; if (x==goal) return -1; for(PII u : spanning[x]) { int y = u.first; int e = u.second; if (y==p) continue; int w = edge[e].w; int res = heaviest(y, x, goal); if (res!=-infty) { if (res==-1 || w>edge[res].w) j = e; else j = res; } } return j; } int main() { int TT; scanf("%d",&TT); while(TT--) { int n, m; scanf("%d%d",&n,&m); edge.resize(m); for(int i=0; i=0; i--) { dprintf("%d: Edge %d - %d (%d).\n",i,edge[i].a,edge[i].b,edge[i].w); int a = edge[i].a; int b = edge[i].b; int j = heaviest(a,-1,b); if (j!=-infty) { dprintf("Displacing %d (%d - %d).\n",j,edge[j].a,edge[j].b); setval(j,0,i); int x = edge[j].a; int y = edge[j].b; for(auto t=spanning[x].begin(); t!=spanning[x].end(); t++) if (t->first ==y) { spanning[x].erase(t); break; } for(auto t=spanning[y].begin(); t!=spanning[y].end(); t++) if (t->first ==x) { spanning[y].erase(t); break; } } setval(i,edge[i].w,i); spanning[a].push_back(PII(b,i)); spanning[b].push_back(PII(a,i)); } int ans = 0; int q; scanf("%d",&q); for(int j=0; j