圆方树前建虚树求调
查看原帖
圆方树前建虚树求调
363006
wangyibo201026楼主2023/10/12 08:29

代码(过样例了,三个 Subtask 全 WA):

#define debug
#include <bits/stdc++.h>

using namespace std;

#define fir first
#define sec second
#define int long long 

char _c; bool _f; template < class T > inline void read ( T &x ) {
	_f = 0, x = 0;
	while ( _c = getchar (), !isdigit (_c) ){
		if ( _c == '-' ) { _f = 1; }
	}
	while ( isdigit (_c) ){
		x = x * 10 + _c - '0', _c = getchar ();
		if (_f) { x = -x; }
	}
}

const int N = 5e5 + 5;

int t, n, m, q, idx, cnt;
int dfn[N << 1], low[N << 1], dd[N << 1], f[N << 1];
vector < int > g[N << 1], p[N << 1];
bool vis[N << 1];

int stk[N << 1], top;

int head[N << 1], tot;

struct Graph {
  int to, next;
} edges[N << 1];

void add ( int u, int v ) {
  tot ++;
  edges[tot].to = v;
  edges[tot].next = head[u];
  head[u] = tot;
}

void tarjan ( int x, int root ) {
	dfn[x] = low[x] = ++ idx;
	stk[++ top] = x;
	for ( int i = head[x]; i; i = edges[i].next ) {
		if ( !dfn[edges[i].to] ) {
			tarjan ( edges[i].to, root );
			low[x] = min ( low[x], low[edges[i].to] );
			if ( low[edges[i].to] >= dfn[x] ) {
			  g[++ cnt].push_back ( x );
				g[x].push_back ( cnt );
				do {
					g[cnt].push_back ( stk[top] );
					g[stk[top]].push_back ( cnt );
				} while ( stk[top --] != edges[i].to );
      }
		}
		else {
			low[x] = min ( low[x], dfn[edges[i].to] );
		}
	}
}

int st[N << 1][25], dep[N << 1], dis[N << 1];

void dfs ( int x, int fa ) {
  dd[x] = ++ idx;
  dep[x] = dep[fa] + 1, dis[x] = dis[fa] + ( x <= n );
  st[x][0] = fa;
  for ( int i = 1; i <= 22; i ++ ) {
    st[x][i] = st[st[x][i - 1]][i - 1];
  }
  for ( int v : g[x] ) {
    if ( v != fa ) {
      dfs ( v, x );
    }
  }
}

int LCA ( int x, int y ) {
  if ( dep[x] > dep[y] ) {
    swap ( x, y );
  }
  for ( int i = 22; i >= 0; i -- ) {
    if ( dep[st[y][i]] >= dep[x] ) {
      y = st[y][i];
    }
  }
  if ( x == y ) {
    return x;
  }
  for ( int i = 22; i >= 0; i -- ) {
    if ( st[x][i] != st[y][i] ) {
      x = st[x][i], y = st[y][i];
    }
  }
  return st[x][0];
}

void Vtree ( vector < pair < int, int > > k ) {
  sort ( k.begin (), k.end () );
  int lim = k.size ();
  for ( int i = 0; i < lim - 1; i ++ ) {
    int elca = LCA ( k[i].second, k[i + 1].second );
    k.push_back ( make_pair ( dd[elca], elca ) );
  }
  sort ( k.begin (), k.end () );
  vector < pair < int, int > > :: iterator it = unique ( k.begin (), k.end () );
  k.erase ( it, k.end () );
  for ( int i = 0; i < k.size () - 1; i ++ ) {
    int elca = LCA ( k[i].second, k[i + 1].second );
    if ( elca != k[i + 1].second ) {
      p[elca].push_back ( k[i + 1].second );
      // cout << k[i].second << " " << k[i + 1].second << " " << elca << '\n';
    }
  }
}

vector < pair < int, int > > tmp;

int disdis ( int x, int y ) {
  return dis[y] - dis[x] - ( y <= n );
}

void ddfs ( int x ) {
  f[x] = 0;
  for ( int v : p[x] ) {
    ddfs ( v );
    f[x] += f[v] + disdis ( x, v );
  }
  if ( !vis[x] && x <= n && ( x != 1 || p[x].size () != 1 ) ) {
    f[x] ++;
  }
  if ( x == 1 && p[x].size () == 1 && !vis[x] ) {
    f[x] -= disdis ( x, p[x][0] );
  }
  p[x].clear ();
  vis[x] = false;
}

void Solve () {
  cin >> t;
  while ( t -- ) {
    tot = idx = cnt = 0;
    memset ( head, 0, sizeof ( head ) );
    cin >> n >> m;
    for ( int i = 1; i <= 2 * n; i ++ ) {
      g[i].clear ();
    }
    for ( int i = 1; i <= m; i ++ ) {
      int u, v;
      cin >> u >> v;
      add ( u, v ), add ( v, u );
    }
    cnt = n;
    for ( int i = 1; i <= n; i ++ ) {
      if ( !dfn[i] ) {
        tarjan ( i, i );
      }
    }
    idx = 0;
    for ( int i = 1; i <= 2 * n; i ++ ) {
      if ( !dd[i] ) {
        dfs ( i, 0 );
      }
    }
    cin >> q;
    while ( q -- ) {
      int k;
      cin >> k;
      tmp.clear ();
      // for ( int i = 1; i <= 2 * n; i ++ ) {
      //   p[i].clear ();
      //   vis[i] = false;
      // }
      for ( int i = 1; i <= k; i ++ ) {
        int x;
        cin >> x;
        tmp.push_back ( make_pair ( dd[x], x ) );
        vis[x] = true;
      }
      tmp.push_back ( make_pair ( dd[1], 1 ) );
      Vtree ( tmp );
      // for ( int i = 1; i <= 2 * n; i ++ ) {
      //   for ( int v : p[i] ) {
      //     cout << i << " " << v << '\n';
      //   }
      // }
      ddfs ( 1 );
      cout << f[1] << '\n';
    }
  }
}

signed main () {
#ifdef debug
	freopen ( "test.in", "r", stdin );
	freopen ( "test.out", "w", stdout );
#endif
    Solve ();
	return 0;
}
2023/10/12 08:29
加载中...