DAY-1

省选前基本没有复习,都在做其他事情。最后周五晚上开了虚拟机想写点板子,结果也没写动,就写了个 A+B。不过把 NOI Linux 2.0 好好试了试,最后在考试前十个小时发现还是 Code::Blocks 最好用(只有CB有补全)。

DAY1

提早了三刻钟到,站了半个小时,然后在要进考场的时候看到了xpt()。进了考场,老师说 Linux 和 Windows 都可以随便选,四周环视了一圈,都是用 Windows 的,不过我还是用了 Linux。打开 Code::Blocks 的时候没找到哪里调编译选项,调了 5 分钟。

T1 一开始不会做,思考了 x=1x=1 的部分分之后想出来了。期望得分:100分。

T2 图论题,不会做,只会枚举每条边是不是新增的然后判断。复杂度 O(n2m)O(n2^m),期望得分:10分。

T3 背景是一棵树,打一个贪心和一个链的特例,期望得分:36分。

DAY2

T1 不会做,只打了第一个特例。期望得分:20分。
T2 感觉和CF某题很像,打了40分部分分。
T3 完全不会,只能输出1。期望得分:2分。

总期望得分 100+10+36+20+40+2=208100+10+36+20+40+2=208

UPD

最后总分 100+0+28+20+28+1=177100+0+28+20+28+1=177,还行,大概上海市前 30 左右。我的评价是:明年继续加油。

赛时代码

station (100)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include<bits/stdc++.h>
using namespace std;

const int N = 2e5+5;

struct Node{
int l,r;
};

int n,m,x;
bool vis[N];
bool isAns[N];
vector<Node> rail;

//void solve(){
// queue<int> q;
// q.push(x);
// vis[x]=1;
// isAns[x]=1;
// vector<int> ans;
//
// while(q.size()){
// int now=q.front();q.pop();
// for(Node r:rail){
// // can go on this rail
//
// // no intersection
// if(r.l>now || r.r<now)continue;
//solve2
// // only right
// if(now>=x){
// for(int j=now+1;j<=r.r;j++){
// if(!vis[j]){
// q.push(j);
// vis[j]=1;
// }
// }
// if(!isAns[r.r]){
// ans.push_back(r.r);
// isAns[r.r]=1;
// }
// }
//
// if(now<=x){
// for(int j=now-1;j>=r.l;j--){
// if(!vis[j]){
// q.push(j);
// vis[j]=1;
// }
// }
//
// if(!isAns[r.l]){
// ans.push_back(r.l);
// isAns[r.l]=1;
// }
// }
// }
// }
//
// sort(ans.begin(),ans.end());
//
// for(auto a:ans){
// printf("%d ",a);
// }
//
// puts("");
//}


bool cmp(const Node& a,const Node& b){
return a.l<b.l;
}
bool cmp2(const Node& a,const Node& b){
return a.r>b.r;
}

//void solve1(){
// sort(rail.begin(),rail.end(),cmp);
// int rightest=1; // the rightest position can reach.
// isAns[1]=1;
// vector<int> ans;
//
// for(auto r:rail){
// // can go to this rail?
// if(r.l <= rightest){
// rightest = max(rightest,r.r);
// if(!isAns[r.r]){
// ans.push_back(r.r);
// isAns[r.r]=1;
// }
// }
// }
//
// sort(ans.begin(),ans.end());
//
// for(auto a:ans){
// printf("%d ",a);
// }
//
// puts("");
//}

void solve2(){
sort(rail.begin(),rail.end(),cmp);
int rightest=x; // the rightest position can reach.
isAns[x]=1;
vector<int> ans;

for(auto r:rail){
// can go to this rail?
// x . . . . . . R
// l r
if(r.l <= rightest && r.r>=x){
rightest = max(rightest,r.r);
if(!isAns[r.r]){
ans.push_back(r.r);
isAns[r.r]=1;
}
}
}
sort(rail.begin(),rail.end(),cmp2);
int leftest=x; // the rightest position can reach.
for(auto r:rail){
// can go to this rail?
if(r.r >= leftest && r.l<=x){
leftest = min(leftest,r.l);
if(!isAns[r.l]){
//printf("left %d is ans, because %d>=%d.\n",r.l,r.r,leftest);
ans.push_back(r.l);
isAns[r.l]=1;
}
}
}

sort(ans.begin(),ans.end());

for(auto a:ans){
printf("%d ",a);
}

puts("");
}

int main(){
freopen("station.in","r",stdin);
freopen("station.out","w",stdout);

scanf("%d%d%d",&n,&m,&x);
for(int i=0;i<m;i++){
int p,q;scanf("%d%d",&p,&q);
rail.push_back({p,q});
}

// if(x==1){
// solve1();
// return 0;
// }


solve2();
return 0;

//
// solve();
// return 0;
}

cities (0)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include<bits/stdc++.h>
using namespace std;

const int N = 2005;

struct Edge{
int u,v;
};
struct Node{
int id,v;
};

int n,m,k;
vector<Edge> edges;
vector<Node> G[N];
bool is_disable_edge[N];
bool is_disable_vert[N];
int cnt_disable_incc[N];
int fa[N];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int i,int j){
fa[find(i)]=fa[find(j)];
}


bool check1(int ed){
// printf("ed : %d\n",ed);
memset(is_disable_vert,0,sizeof(is_disable_vert));
int cnt_edge=0;
for(int i=0;i<m;i++){
if(ed & (1<<i)){
// printf("\t %d,%d is ok.\n",ed,i);
// printf("\t\t %d | %d = %d\n",ed,(1<<i),ed|(1<<i));
is_disable_edge[i]=1;cnt_edge++;
is_disable_vert[edges[i].u]=1;
is_disable_vert[edges[i].v]=1;
}
else is_disable_edge[i]=0;
}

int cnt_vert=0;
for(int i=1;i<=n;i++){
if(is_disable_vert[i])cnt_vert++;
}

// t-edge of t-vertex
if(cnt_vert != cnt_edge)return 0;

// =======================================
// the count of CC is t
// =======================================

// init the DSU
for(int i=1;i<=n;i++){
fa[i]=i;
}
for(int i=0;i<m;i++){
if(!is_disable_edge[i]){
merge(edges[i].u,edges[i].v);
}
}

int cnt_cc = 0;
for(int i=1;i<=n;i++){
if(fa[i]==i)cnt_cc++;
}
if(cnt_cc != cnt_vert)return 0;

// =======================================
// each CC has and only has ONE disabled vertex
// =======================================

memset(cnt_disable_incc,0,sizeof cnt_disable_incc);
for(int i=1;i<=n;i++){
if(is_disable_vert[i]){
cnt_disable_incc[fa[i]]++;
}
}

for(int i=1;i<=n;i++){
if(cnt_disable_incc[fa[i]]!=1)return 0;
}
// for(int i=0;i<m;i++){
// if(is_disable_edge[i]){
// printf("(%d,%d) ",edges[i].u,edges[i].v);
// }
// }
// printf(" is valid.\n");
return 1;
}

int main(){
freopen("cities.in","r",stdin);
freopen("cities.out","w",stdout);

scanf("%d%d%d",&n,&m,&k);

for(int i=0;i<m;i++){
int u,v;
scanf("%d%d",&u,&v);
edges.push_back({u,v});
int sz = edges.size()-1;
G[u].push_back({sz,v});
G[v].push_back({sz,u});
}

int ans = 0;
for(int i=1;i<=(1<<m);i++){ // i: the set of edges that is added
if(check1(i))ans++;
}
printf("%d\n",ans);
return 0;
}

transfer (28)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include<bits/stdc++.h>
using namespace std;

const int N = 1e5+5;

struct Employee{
int id,abl;

bool operator<(const Employee& rhs)const{
return abl<rhs.abl;
}
};

int n,k,m;
vector<Employee> emp[N]; // the employee of this Node
int emp_pos[N]; // the initial position of employee X
vector<int> G[N]; // the tree.

vector<Employee> emp2[N];



void try_place(int pos,int fa,vector<Employee>::iterator need_to_place){
int best_pos=-1,best_val=-1;
// bfs all children
queue<pair<int,int> > q;
q.push({pos,fa});
while(q.size()){
auto now = q.front();q.pop();

int maxn = 0; // the maximum ability of Node now. 0 for no employee
for(auto people:emp2[now.first]){
maxn = max(maxn,people.abl);
}
// only can move if the target has lower ability
if(maxn<need_to_place->abl){
if(best_pos==-1 || maxn<best_val){
best_pos=now.first;
best_val=maxn;
}
}



for(int ch:G[now.first]){
if(ch!=now.second){
q.push({ch,now.first});
}
}
}

if(best_pos != -1){
emp2[best_pos].push_back(*need_to_place);
emp2[pos].erase(need_to_place);
}
}

void dfs(int u,int f){
// search the children first.
for(int v:G[u]){
if(v==f)continue;
dfs(v,u);
}

// try to change the people
// only need to change if there's more than one people.
if(emp2[u].size()<=1)return;

// find the best position to fit the person in
// empty -> lower ability.

sort(emp2[u].begin(),emp2[u].end());
for(int i=emp2[u].size()-2;i>=0;i--){
try_place(u,f,emp2[u].begin()+i);
}
}

void solve(){
for(int i=1;i<=n;i++){
emp2[i] = emp[i];
}
dfs(1,1);

// calculate the answer
long long ans = 0;
for(int i=1;i<=n;i++){
if(emp2[i].size())
ans += max_element(emp2[i].begin(),emp2[i].end())->abl;
}
printf("%lld ",ans);
}

//struct NodeChain{
// int val,pos; // the pos's biggest is val.
// bool operator<(const NodeChain& rhs)const{
// return val>rhs.val;
// }
//};

int get_max(int id){
int maxn = 0;
for(auto people:emp[id]){
maxn=max(maxn,people.abl);
}
return maxn;
}

void solve_chain(){
priority_queue<int,vector<int>,greater<int> > pq; // samll heap
// 1 -> 2 -> 3 ... -> n-1 -> n
// start from the n-1 pos.

long long ans = 0;
ans += get_max(n);
pq.push(ans);
// printf("%lld first pushed.\n",ans);

for(int i=n-1;i>=1;i--){
// i can go to i+1 ... n
// the top of pq(samllest)

// for every people except the biggest.
int mi = get_max(i);
ans += mi;
pq.push(mi);
// printf("%d pushed.\n",mi);
bool max_appeared = 0;
for(auto p:emp[i]){
if(p.abl!=mi || max_appeared){
if(pq.top()<p.abl){
ans -= pq.top(); ans += p.abl;
pq.pop();pq.push(p.abl);
}
}else{
max_appeared=1;
}
}
}

printf("%lld ",ans);
}

int main(){
freopen("transfer.in","r",stdin);
freopen("transfer.out","w",stdout);

int sid;scanf("%d",&sid);


scanf("%d%d%d",&n,&k,&m);

for(int i=2;i<=n;i++){
int v;scanf("%d",&v);
G[i].push_back(v);G[v].push_back(i);
}

for(int i=1;i<=k;i++){
int x,v;scanf("%d%d",&x,&v);
emp[x].push_back({i,v});
emp_pos[i]=x;
}


if(sid==6){
solve_chain();
return 0;
}

solve();
for(int i=1;i<=m;i++){
int op;scanf("%d",&op);
if(op==1){
int x,v;scanf("%d%d",&x,&v);
emp[x].push_back({++k,v});
emp_pos[k]=x;
}
else{
int ide;scanf("%d",&ide);
int p = emp_pos[ide];
for(auto it=emp[p].begin();it<emp[p].end();it++){
if(it->id == ide){
emp[p].erase(it);
break;
}
}
}
solve();
}
return 0;
}

zu (20)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include<bits/stdc++.h>
using namespace std;

// 114514
// 1919810
// hai you yi ge xiao shi. xie bu chu lai le ;(

char mp[15][15];

int dx_r[]={1,-1,0,0};
int dy_r[]={0,0,1,-1};

int n,m;


void solve_p1(){
// can red move?
bool can_red_move = 0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]!='O')continue;
for(int k=0;k<4;k++){
int ii=i+dx_r[k],jj=j+dy_r[k];
// because tie or red can't move
// so red can never move to a black piece.
// only check if empty
if(mp[ii][jj]=='.')can_red_move=1;
}
}
}
if(!can_red_move){
puts("Black 0");
}
else{
puts("Tie");
}
}

void solve_1b1r(){
// iiyo koiyo
// if m==1 ->
if(m==1){
// black wins iff there's only . above it.
int bx,bo;
for(int i=1;i<=n-2;i++){
if(mp[i][1]=='X'){
bx=i;
}
if(mp[i][1]=='O'){
bo=i;
}
}
}


// else
// NOTE THAT red CAN SKIP his round (the piece in line n can move)


// strategy
// black : move forward
// red : first move horizontally, then move vertically.
// wrong
puts("Tie");
}

void solve_long(){
// black:only can move forward

// 1. check if red can move.
bool can_red_move = 0;
bool can_eat_black = 0;
for(int i=1;i<=n;i++){
if(mp[i][1] != 'O')continue;
if(mp[i-1][1]=='.' || mp[i+1][1] == '.')can_red_move=1;
if(mp[i-1][1]=='X' || mp[i+1][1] == 'X')can_eat_black=1;
}
if(can_eat_black){
puts("Red 1");
return;
}
if(!can_red_move){
puts("Black 0");
return;
}

// black win if there's only '.'
int bx;
for(int i=1;i<=n;i++){
if(mp[i][1]=='X'){
bx=i;break;
}
}
bool can_move_black = ((mp[bx-1][1]=='.') || (mp[bx+1][1]=='.'));

// black can't move but red can. red win after an arbitrary move.
if(!can_move_black){
puts("Red 1");
return;
}

bool have_obstacle = 0;
for(int i=bx-1;i<=1;i--){
if(mp[i][1]!='.'){
have_obstacle = 1;
}
}
if(!have_obstacle){
printf("Black %d\n",bx-1);
return;
}

// if black can never move to red, then must tie.
// 1) search above.
int can_meet = 0;
for(int i=bx-1;i>0;i--){
if(mp[i][1]=='#')break;
if(mp[i][1]=='O')can_meet++;
}
// 2) search below.
for(int i=bx+1;i<=n;i++){
if(mp[i][1]=='#')break;
if(mp[i][1]=='O')can_meet++;
}
if(!can_meet){
puts("Tie");
return;
}


// the last task is divided into the following three subtasks.
// a) 2 red 1 black
// b) 1 red 1 black (other red can't move)
// c) 1 red 1 black (other red can move)

// greedy ok?
// shirazu

// a)
/* (= stands for \.*)
=
R
=
R
=
B
=
*/

// Can eat?
puts("Tie");
}

void solve_bf(){
puts("Tie");

}

int main(){
freopen("zu.in","r",stdin);
freopen("zu.out","w",stdout);

int id,T;
scanf("%d%d",&id,&T);
while(T--){
scanf("%d%d",&n,&m);
memset(mp,0,sizeof(mp));
for(int i=0;i<n;i++){
scanf("%s",mp[i+1]+1);
}

if(1<=id && id<=4){
solve_p1();
}
else if(5<=id && id<=6){
solve_1b1r();
}
else if(7<=id && id<=9||m==1){
solve_long();
}
else if(10<= id && id<=13){
solve_bf();
}
else{
solve_p1();
}

}
return 0;
}

game (28)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
// too hard
#include<bits/stdc++.h>
using namespace std;

const int N = 1e5+5;
const int INF = 0x3f3f3f3f;

int kase;
int n,m;
int S[N][4],T[N][4];
int vis[20];
int a[N],b[N];
int ans;
int tans;

void dfs2(int dep){
if(dep==n){
// printf("[%d]",kase);
// for(int i=0;i<n;i++){
// printf("%d ",a[i]);
// }
// printf("/ ");
// for(int i=0;i<n;i++){
// printf("%d ",b[i]);
// }

// check if subete ha kotonarimasu.
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++){
if(vis[b[i]]==1){
// printf("same!\n");
return;
}
vis[b[i]]=1;
}
// for all possible move, bob will choose the minimal one.
int eq = 0;
for(int i=0;i<n;i++){
if(a[i]==b[i])eq++;
}
tans = min(tans,eq);
// printf("ok, eq=%d tans=%d\n",eq,tans);
return;
}
for(int i=1;i<=T[dep][0];i++){
b[dep]=T[dep][i];
dfs2(dep+1);
}
}
void dfs1(int dep){
if(dep==n){
tans = INF;
dfs2(0);

// for all possible tans, Alice will choose the greatest.
if(tans!=INF)ans=max(ans,tans);
return;
}
for(int i=1;i<=S[dep][0];i++){
a[dep]=S[dep][i];
dfs1(dep+1);
}
}
void solve_bf(){
ans = -1;
dfs1(0);
printf("%d\n",ans);
}


int fa[N],sz[N];
int cnt[N];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int i,int j){
// printf("\tmerge %d(%d/%d), %d(%d/%d)\n",i,find(i),sz[find(i)],j,find(j),sz[find(j)]);
i=find(i),j=find(j);
if(i==j)return;
if(sz[i]>sz[j])swap(i,j);
fa[i]=j;
sz[j]+=sz[i];
}
void solveA(){
// puts("great! is A!");
// zhe shi CF yuan ti
// dan shi wo wang le ?
// ...
// suo yi shuo yao bu ti. QAQ
// ming nian zai zhan

// (10:25)我觉得如果每个连通块内边数小于等于点数就可以
// 否则就不可以

// (10:44) wonderfully, it works!
// but i don't know why it works
// it just works perfectly.
// watashiha tennsai da!

for(int i=1;i<=m;i++){
fa[i]=i;sz[i]=1;
cnt[i]=0;
}

for(int i=0;i<n;i++){
if(T[i][0]>1){
merge(T[i][1],T[i][2]);
}
}

for(int i=0;i<n;i++){
cnt[find(T[i][1])]++;
}

bool ok = 1;
for(int i=1;i<=m;i++){
if(find(i)==i){
// printf("\tSCC %d (%d node, %d edge).\n",i,sz[i],cnt[i]);
if(cnt[i]>sz[i]){
ok=0;break;
}
}
}
if(ok)puts("0");
else puts("-1");
}
//int cntk=0;

void solveB(){
// printf("SUBARASHII BIDESU!\n");
// 1,2,3,...,n
// 2,3,4,...,1

// check S
// if all not the same -> give up.
// if one is same -> choose the same one.
// if two is same -> wait.

int ans1=0,ans2=0;
int tsame = 0;
for(int i=0;i<n;i++){
int t1 = i+1, t2 = i+2;
if(t2==n+1)t2=1;


if(S[i][0]==1){ // 1) |S| = 1
if(S[i][1]==t1)ans1++;
if(S[i][1]==t2)ans2++;
}
else{ // 2) |S| = 2
// make it ordered (it's wrong. just test all orders).
if((S[i][1] == t1 && S[i][2] == t2) ||
(S[i][1] == t2 && S[i][2] == t1))tsame++;
else if(S[i][1]==t1 || S[i][2]==t1)ans1++;
else if(S[i][1]==t2 || S[i][2]==t2)ans2++;
}


}

// if(cntk==16){
// printf("a1: %d, a2:%d, t:%d\n",ans1,ans2,tsame);
// }


// greedy
// if is ANS1 -> Alice will choose it equal I
// if is ANS2 -> Alice will choose it equal I+1

// tsame can be added to ans1/ans2.
// goal: make the minimum of the two number is greatest.

// first, try to make the two number same.
if(ans1>ans2)swap(ans1,ans2);
if(tsame>0){

// ans1 < ans2.
if(tsame >= ans2-ans1){
tsame -= ans2-ans1;
ans1=ans2;
}
else{
ans1+=tsame;
tsame=0;
}
// ans1 += min(ans2-ans1,tsame);
}

// if(cntk==16){
// printf("#after proc1\n");
// printf("a1: %d, a2:%d, t:%d\n",ans1,ans2,tsame);
// }

// now the two are the same.
// both add (tsame//2) (the remainder 1 can be omitted -> no affect answer)
if(tsame>0){
ans1 += tsame/2;
ans2 += tsame/2;
}
printf("%d\n",min(ans1,ans2));
}
int main(){
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
scanf("%d",&kase);
while(kase--){
// cntk++;
scanf("%d%d",&n,&m);
bool isA = 1;
bool isB = (n>=3);

for(int i=0;i<n;i++){
scanf("%d",&S[i][0]);
for(int j=1;j<=S[i][0];j++){
scanf("%d",&S[i][j]);
}
}
for(int i=0;i<n;i++){
scanf("%d",&T[i][0]);
if(T[i][0]==1)isB=0;
for(int j=1;j<=T[i][0];j++){
scanf("%d",&T[i][j]);
// check if is same.
if(!isA)continue;
for(int k=1;k<=S[i][0];k++){
if(S[i][k]==T[i][j])isA=0;
}
}
if(!isB)continue;
// check is is B
// 1) sort them
if(T[i][1]>T[i][2])swap(T[i][1],T[i][2]);

if(i==n-1){
if(T[i][1] != 1)isB=0;
if(T[i][2] != n)isB=0;
}
else{
if(T[i][1] != i+1)isB=0;
if(T[i][2] != i+2)isB=0;
}

// if(!isB){
// printf("T[%d] = {%d,%d} failed! (should = {%d,%d})\n",
// i,T[i][1],T[i][2],i+1,(i==n-1)?1:(i+2));
// }
}

// if(cntk==16){
// printf("Test Case 16:\n");
// for(int i=0;i<n;i++){
// printf("[%d](%d,%d)\n",S[i][0],S[i][1],S[i][2]);
// }
// }

if(isB){
solveB();
continue;
}
if(isA){
solveA();
continue;
}
if(n<=10 && m<=10){
solve_bf();
continue;
}
}
return 0;
}

color (1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<bits/stdc++.h>
using namespace std;

int main(){
freopen("color.in","r",stdin);
freopen("color.out","w",stdout);
int T;scanf("%d",&T);
while(T--){
puts("1 1"); // 2 points got
// trust the data of CCF
// bukeyi zongsiling
}
return 0;
}