人菜就要少揽事,呵呵~~~ 忙了两天一夜,有什么用。
WA RE 交替中度过,还是太SB,太相信那个’有根’一词了。
一、有根树,但是边是无向的;
二、在预处理DFS信息时,用邻接表存图。
题意:定义
u
是合法点
1、
2、
u
是某两个不同重要点的最近公共祖先。
每次给定非重要点,问你一共有多少个合法点。
思路:显然只要
定义
这样若
非重要点数目很少,而重要点的信息我们也不需要,这样可以根据父子关系重新建个图,跑搜索即可。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 100;
const int MOD = 1e9 + 7;
struct Edge {
int to, next;
};
Edge edge[MAXN * 2];
int head[MAXN], edgenum;
void addEdge(int u, int v) {
Edge E = {v, head[u]};
edge[edgenum] = E;
head[u] = edgenum++;
}
void add(LL &x, LL y) {
x += y;
if(x >= MOD) x -= MOD;
}
vector<int> G[MAXN];
bool vis[MAXN];
int son[MAXN], pre[MAXN];
int ans;
void Init(int u, int fa) {
for(int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].to;
if(v == fa) continue;
Init(v, u);
son[u]++; pre[v] = u;
}
}
bool DFS(int u) {
// true all important
// false not
int cnt = 0;
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(DFS(v)) {
cnt++;
}
}
if(son[u] - cnt >= 2) {
ans++;
}
if(cnt == son[u]) return true;
return false;
}
int x[MAXN];
int in[MAXN];
int main()
{
int t, kcase = 1; scanf("%d", &t);
while(t--) {
int n, q; scanf("%d%d", &n, &q);
for(int i = 1; i <= n; i++) {
vis[i] = false; son[i] = 0;
//G[i].clear();
head[i] = -1;
}
edgenum = 0; pre[1] = -1;
for(int i = 1; i <= n - 1; i++) {
int u, v; scanf("%d%d", &u, &v);
addEdge(u, v);
addEdge(v, u);
//G[u].push_back(v);
//G[v].push_back(u);
}
Init(1, -1);
//for(int i = 1; i <= n; i++) G[i].clear();
printf("Case #%d:\n", kcase++);
while(q--) {
int m; scanf("%d", &m);
ans = n - m;
for(int i = 1; i <= m; i++) {
scanf("%d", &x[i]);
vis[x[i]] = true;
G[x[i]].clear();
in[x[i]] = 0;
}
for(int i = 1; i <= m; i++) {
if(pre[x[i]] != -1 && vis[pre[x[i]]]) {
G[pre[x[i]]].push_back(x[i]);
in[x[i]]++;
}
}
for(int i = 1; i <= m; i++) {
if(in[x[i]] == 0) {
DFS(x[i]);
}
vis[x[i]] = false;
}
printf("%d\n", ans);
}
}
return 0;
}
hdoj 5929 Basic Data Structure
题意:有若干个操作。
反转栈,元素进栈,出栈,查询
发现元素 0 <script type="math/tex" id="MathJax-Element-13">0</script>的特殊性,那么就用一个双端队列去维护,维护的信息是每个0前面连续1的个数。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int Queue[400000 + 10];
int main()
{
int T, kcase = 1; scanf("%d", &T);
while(T--) {
int N; scanf("%d", &N);
for(int i = 0; i <= 2 * N + 10; i++) Queue[i] = 0;
bool flag = true;
int L, R; L = R = N;
int cnt = 0;
printf("Case #%d:\n", kcase++);
for(int i = 0; i < N; i++) {
char op[10]; int v;
scanf("%s", op);
if(op[0] == 'P') {
if(op[1] == 'U') {
scanf("%d", &v);
if(flag) {
if(v == 0) {
Queue[R++] = cnt + 1;
cnt = 0;
}
else {
cnt++;
}
}
else {
if(v == 0) {
Queue[--L] = 1;
}
else {
if(L != R) {
Queue[L]++;
}
else {
cnt++;
}
}
}
}
else {
if(flag) {
if(cnt == 0) {
cnt = Queue[R - 1] - 1;
Queue[R - 1] = 0; R--;
}
else {
cnt--;
}
}
else {
if(L != R) {
if(--Queue[L] == 0) {
L++;
}
}
else {
cnt--;
}
}
}
}
else if(op[0] == 'Q') {
if(L == R) {
if(cnt == 0) {
printf("Invalid.\n");
}
else {
if(cnt & 1) {
printf("1\n");
}
else {
printf("0\n");
}
}
}
else if(!flag) {
if(L == R - 1 && Queue[R - 1] == 1) { // 0
if(cnt & 1) {
printf("1\n");
}
else {
printf("0\n");
}
}
else { // 1
if(cnt & 1) {
printf("0\n");
}
else {
printf("1\n");
}
}
}
else {
if(L == R - 1 && cnt == 0) { // 0
if((Queue[L] - 1) & 1) {
printf("1\n");
}
else {
printf("0\n");
}
}
else { // 1
if((Queue[L] - 1) & 1) {
printf("0\n");
}
else {
printf("1\n");
}
}
}
}
else {
flag = !flag;
}
}
}
return 0;
}