2016CCPC东北赛 (A、C、E、H、F、D)( 水题 + 结论 + 水模拟 + 复杂模拟 + LCA思维 + 二维坐标带权离散化 )

A - Minimum’s Revenge

 

There is a graph of n vertices which are indexed from 1 to n. For any pair of different vertices, the weight of the edge between them is the  least common multiple of their indexes. 

Mr. Frog is wondering about the total weight of the minimum spanning tree. Can you help him? 
InputThe first line contains only one integer T ( T100T≤100), which indicates the number of test cases. 

For each test case, the first line contains only one integer n ( 2n1092≤n≤109), indicating the number of vertices. 
OutputFor each test case, output one line "Case #x:y",where x is the case number (starting from 1) and y is the total weight of the minimum spanning tree. 
Sample Input
2
2
3
Sample Output
Case #1: 2
Case #2: 5

        
  
Hint
In the second sample, the graph contains 3 edges which are (1, 2, 2), (1, 3, 3) and (2, 3, 6). Thus the answer is 5.
 

A:编号为1~n的n个节点,任意两点之间的边权为两点编号的LCM,问这个图的最小生成树权值。

最水的签到题,这道题一开始开场就看到的水题,然后因为把LCM看成GCD还蒙了一下,整明白之后知道是到求和题就直接码了,还担心罚时所以检查了一遍才交 TAT

#include<bits/stdc++.h>
using namespace std;

int main()
{
    long long n, sum = 0;
    int T;
    scanf("%d", &T);
    for(int i=1; i<=T; i++){
        scanf("%lld", &n);
        sum = (2+n)*(n-1)/2;
        printf("Case #%d: %lld\n", i, sum);
    }
}

C - Mr. Frog’s Problem

One day, you, a clever boy, feel bored in your math class, and then fall asleep without your control. In your dream, you meet Mr. Frog, an elder man. He has a problem for you. 

He gives you two positive integers A and B, and your task is to find all pairs of integers (C, D), such that  ACB,ADBand  AB+BACD+DC
Inputfirst line contains only one integer T ( T125  ), which indicates the number of test cases. Each test case contains two integers A and B ( 1AB1018).OutputFor each test case, first output one line "Case #x:", where x is the case number (starting from 1). 

Then in a new line, print an integer s indicating the number of pairs you find. 

In each of the following s lines, print a pair of integers C and D. pairs should be sorted by C, and then by D in ascending order. 
Sample Input
2
10 10
9 27
Sample Output
Case #1:
1
10 10
Case #2:
2
9 27
27 9
 

C题:给定区间A, B求解满足要求的CD,并按照C的升序输出。

这是我们队全场A出的第二题,也是一道签到题,当时莽了一发特判AB相等不然互换的结论就过了,场后学妹表示可以用斜率证明,学妹V5。

#include<bits/stdc++.h>
using namespace std;



int main()
{
    long long a, b;
    int T;
    scanf("%d", &T);
    for(int i=1; i<=T; i++){

        scanf("%lld%lld", &a, &b);
        printf("Case #%d:\n", i);
        if(a == b){
            printf("1\n");
            printf("%lld %lld\n", a, b);
        }
        else {
            printf("2\n");

            long long aa = min(a, b);
            long long bb = max(a, b);

            printf("%lld %lld\n", aa, bb);
            printf("%lld %lld\n", bb, aa);
        }
    }
    return 0;
}

E - Mr. Frog’s Game

 
One day, Mr. Frog is playing Link Game (Lian Lian Kan in Chinese). 



In this game, if you can draw at most three horizontal or vertical head-and-tail-connected lines over the empty grids(the lines can be out of the whole board) to connect two non-empty grids with the same symbol or the two non-empty grids with the same symbol are adjacent, then you can change these two grids into empty and get several more seconds to continue the game. 

Now, Mr. Frog starts a new game (that means there is no empty grid in the board). If there are no pair of grids that can be removed together,Mr. Frog will say ”I’m angry” and criticize you. 

Mr. Frog is battle-scarred and has seen many things, so he can check the board in a very short time, maybe one second. As a Hong Kong Journalist, what you should do is to check the board more quickly than him, and then you can get out of the room before Mr. Frog being angry. 
InputThe first line contains only one integer T ( T500T≤500), which indicates the number of test cases. 

For each test case, the first line contains two integers n and m ( 1n,m301≤n,m≤30). 

In the next n lines, each line contains m integers,  j-th number in the i-th line means the symbol on the grid(the same number means the same symbol on the grid). 
OutputFor each test case, there should be one line in the output. 

You should output “Case #x: y”,where x is the case number(starting from 1), and y is a string representing the answer of the question. If there are at least one pair of grids that can be removed together, the y is “Yes”(without quote), else y is “No”.Sample Input
2
3 3
1 2 1
2 1 2
1 2 1
3 3
1 2 3
2 1 2
3 2 1
Sample Output
Case #1: Yes
Case #2: No

 

E题:E题是学妹做的,听说是一道只判边缘相同的连连看水题,并没有看...直接放ac代码吧。

#include <bits/stdc++.h>
using namespace std;
const int maxn=33;
int mp[maxn][maxn];
int meo[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
int n,m;
bool check()
{
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            if(i==j) continue;
            if(mp[i][m]==mp[j][m])
                return true;
        }
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            if(i==j) continue;
            if(mp[i][1]==mp[j][1])
                return true;
        }
    }
    for(int i=1; i<=m; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if(i==j) continue;
            if(mp[n][i]==mp[n][j])
                return true;
        }
    }
    for(int i=1; i<=m; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if(i==j) continue;
            if(mp[1][i]==mp[1][j])
                return true;
        }
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            for(int t=0; t<4; t++)
            {
                int x=i+meo[t][0];
                int y=j+meo[t][1];
                if(mp[x][y]==mp[i][j])
                    return true;
            }
        }
    }
    return false;
}
int main()
{
    int t;
    cin>>t;
    int cas=1;
    while(t--)
    {
       // int n,m;
        cin>>n>>m;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                cin>>mp[i][j];
            }
        }
        //cas=1;
        //cout<<"Case #"<<cas++<<':'<<' ';
        printf("Case #%d: ",cas++);
        if(check())
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    }
    return 0;
}
H - Basic Data Structure

Mr. Frog learned a basic data structure recently, which is called stack.There are some basic operations of stack: 

 PUSH x: put x on the top of the stack, x must be 0 or 1. 
 POP: throw the element which is on the top of the stack. 

Since it is too simple for Mr. Frog, a famous mathematician who can prove "Five points coexist with a circle" easily, he comes up with some exciting operations: 

REVERSE: Just reverse the stack, the bottom element becomes the top element of the stack, and the element just above the bottom element becomes the element just below the top elements... and so on. 
QUERY: Print the value which is obtained with such way: Take the element from top to bottom, then do  NAND operation one by one from left to right, i.e. If   atop,atop1,,a1atop,atop−1,⋯,a1 is corresponding to the element of the Stack from top to the bottom,  value=atopvalue=atop nand  atop1atop−1 nand ... nand  a1a1. Note that the Stack  will not change after QUERY operation. Specially, if the Stack is empty now,you need to print ” Invalid.”(without quotes). 

By the way,  NAND is a basic binary operation: 

 0 nand 0 = 1 
 0 nand 1 = 1 
 1 nand 0 = 1 
 1 nand 1 = 0 

Because Mr. Frog needs to do some tiny contributions now, you should help him finish this data structure: print the answer to each QUERY, or tell him that is invalid. 
InputThe first line contains only one integer T ( T20T≤20), which indicates the number of test cases. 

For each test case, the first line contains only one integers N ( 2N2000002≤N≤200000), indicating the number of operations. 

In the following N lines, the i-th line contains one of these operations below: 

 PUSH x (x  must be 0 or 1) 
 POP 
 REVERSE 
 QUERY 

It is guaranteed that the current stack will not be empty while doing POP operation.
OutputFor each test case, first output one line "Case #x:w, where x is the case number (starting from 1). Then several lines follow,  i-th line contains an integer indicating the answer to the i-th QUERY operation. Specially, if the i-th QUERY is invalid, just print "  Invalid."(without quotes). (Please see the sample for more details.) 
Sample Input
2
8
PUSH 1
QUERY
PUSH 0
REVERSE
QUERY
POP
POP
QUERY
3
PUSH 0
REVERSE
QUERY
Sample Output
Case #1:
1
1
Invalid.
Case #2:
0

H:模拟一个可以翻转的栈,包含PUSH x; POP; REVERSE;QUERY查询的是从栈顶往下做与非运算的结果。

开场想到可以用双端队列(deque)模拟这个可以翻转的栈,之后在讨论中判断出最后的值只和栈底连续的1的个数有关,于是决定将连续的1以计数的方式入队,这样每次查询的时候可以直接O1判断出最后的结果。但是犯错WA了几发,原因是我认为从栈底往上第一个0相当于将之前全部置1,因为0与非任何数都得0。所以就只加了对size==1的判断,但是经过学弟提醒,当你只有一个1的时候,0代表的就是0他是没有计算过与非的。于是就又加了size==2的判断。学弟V5

#include<bits/stdc++.h>
using namespace std;

deque<int > dq;
char op[20];


int main()
{
    int T, cas = 1;
    scanf("%d", &T);
    while(T--)
    {
        int flag =  1;
        dq.clear();
        int n;
        scanf("%d", &n);
        printf("Case #%d:\n", cas++);
        while(n--)
        {
            scanf("%s", op);
            if(op[2] == 'S') //push
            {
                int num;
                scanf("%d", &num);

                if(dq.empty())
                    dq.push_back(num);
                else if(!num) {// num == 0
                    if(flag)   // front is top
                        dq.push_front(num);

                    else       // back is top
                        dq.push_back(num);
                }
                else { // num == 1
                    if(flag){    // front is top
                        int t = dq.front();
                        if(t==0)
                            dq.push_front(num);
                        else {
                            dq.pop_front();
                            dq.push_front(t+1);
                        }
                    }
                    else{       // back is top
                        int t = dq.back();
                        if(t==0)
                            dq.push_back(num);
                        else {
                            dq.pop_back();
                            dq.push_back(t+1);
                        }
                    }
                }
            }

            else if(op[2] == 'V')  //reverse
                flag ^= 1;    //reverse

            else if(op[2] == 'P')  // pop
            {
                if(flag){    // front is top
                    int t = dq.front();
                    if(t == 0 || t == 1)
                        dq.pop_front();
                    else{
                        dq.pop_front();
                        dq.push_front(t-1);
                    }
                }
                else {      // back is top
                    int t = dq.back();
                    if(t == 0 || t == 1)
                        dq.pop_back();
                    else{
                        dq.pop_back();
                        dq.push_back(t-1);
                    }
                }
            }
            else if(op[2] == 'E') // query
            {
                int t;
                if(dq.empty()){
                    puts("Invalid.");
                    continue;
                }
                else if(flag) // front is top
                    t = dq.back();
                else          // back is top
                    t = dq.front();

                if(dq.size()==1) {
                    if(t == 0) puts("0");
                    else if(t%2) puts("1");
                    else puts("0");
                }
                else if(dq.size() == 2){
                    if(t==0) puts("1");
                    else if(t%2) puts("1");
                    else puts("0");
                }

                else{
                    if(t == 0) puts("1");
                    else if(t%2) puts("0");
                    else puts("1");
                }
            }

//            for(deque<int>::iterator it = dq.begin(); it!=dq.end(); it++)
//                printf("%d ", *it);
//            puts("");
        }
    }
    return 0;
}

这道题如果把PUSH、POP、QUE、REV操作全部拉出来单列成函数可能会更加清晰一点,但是我懒得弄了,场上是按做一个复杂模拟写的Orz

三个小时的训练场,A出来四题,之后的是补出来的两题。

F - Auxiliary Set

 

Given a rooted tree with n vertices, some of the vertices are important. 

An auxiliary set is a set containing vertices satisfying at least one of the two conditions: 

It is an important vertex 
It is the least common ancestor of two different important vertices. 

You are given a tree with n vertices (1 is the root) and q queries. 

Each query is a set of nodes which indicates the  unimportant vertices in the tree. Answer the size (i.e. number of vertices) of the auxiliary set for each query. 
InputThe first line contains only one integer T ( T1000), which indicates the number of test cases. 

For each test case, the first line contains two integers n ( 1n100000), q ( 0q100000     ). 

In the following n -1 lines, the i-th line contains two integers  ui,vi(1ui,vin)ui,vi(1≤ui,vi≤n)indicating there is an edge between  uiuii and  vivi in the tree. 

In the next q lines, the i-th line first comes with an integer  mi(1mi100000)         indicating the number of vertices in the query set.Then comes with mi different integers, indicating the nodes in the query set. 

It is guaranteed that  qi=1mi100000

It is also guaranteed that the number of test cases in which  n1000  or  qi=1mi1000 is no more than 10. 
OutputFor each test case, first output one line "Case #x:", where x is the case number (starting from 1). 

Then q lines follow, i-th line contains an integer indicating the size of the auxiliary set for each query. 
Sample Input
1
6 3
6 4
2 5
5 4
1 5
5 3
3 1 2 3
1 5
3 3 1 4
Sample Output
Case #1:
3
6
3

F题:题目给出一颗根为1的有根树。然后每次给出你一个不重要点的集合(其他点都是重要的),问你好点的个数。而好点有两个定义,一个是它本身是重要的,第二个是它是两个好点的LCA

一开始以为这道题要用LCA去写,但是因为不愿意(其实是因为不会)所以决定用pre数组去存前驱节点的信息,然后往回遍历的方式去把不重要的点转换求解,然后WA了。

第二天补题时候打算去学一下LCA但是回头看看这道题,不重要的点个数偏少,而重要的点特别的多,如果我枚举重要的点对,然后再去找他们的LCA,这个时间复杂度其实是O(n^2logn)的,很明显对于此中数据并不能通过,然后想了想一定是有什么高端的LCA算法是我没有掌握的,但是一时半会儿又不想去学,就打算回归题目本身再去想一下。

之后观察到不重要的点个数很少,那我们能不能通过判断不重要的点能不能转化为好点来求解。然后我们得到了不重要的点嗯那个转化为好点的条件:他的所有子节点为根的子树中,只要有两个以上子树中含有重要的点,那么这个节点就是两个重要的点的LCA。那么我们就变成了,按照深度降序访问所有不重要的节点(深度降序保证了之前的访问不会影响到之后的),如果当前不好的节点没有子节点,那么它一定是坏点,且它引导的子树对父亲节点没有贡献,那么就让父亲节点的子节点数--, 如果它有一个子节点,那么这个点不能转化为好点,但是它引导的子树依然有贡献,不做处理。如果它有两个以上的子节点,那么也就是说这个点可以转化为好点,且对父亲节点有贡献,cnt++

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+5;

struct Node{
    int num = 0;    //子节点个数(分支个数)
    int pre = -1;   //父亲节点编号
    int id = 1;     //当前节点编号
    int val = -1;   //用于在同一个图的不同询问中,判断有贡献的分支数量
    int dep;        //树深,dfs中赋值,用于在set中排序

    bool  operator < (const Node &b) const{   // sort in set depend on depth
                                              //重写小于运算符,便于在set中排序
        if(dep!=b.dep)
            return dep > b.dep;               //第一排序方式是深度
        else return id < b.id;                //第二排序方式是id, 不加这个判断的话,会因为相同深度被set去重
    }

}a[maxn];

set<Node >s;
vector<int >edge[maxn];
bool vis[maxn];


void init(int n)   // init a[1, n]
{
    for(int i=0; i<maxn; i++)
        edge[i].clear();
    memset(vis, 0, sizeof vis);
    vis[1] = 1;
    for(int i=0; i<=n+1; i++){
        a[i].id = i;
        a[i].num = 0;
        a[i].val = -1;
    }
    return ;
}

void dfs(int n, int dep)
{
    a[n].dep = dep;
    //printf("***%d: %d\n", n, dep);
    for(int i=0; i<edge[n].size(); i++)
    {
        if(!vis[edge[n][i]]){
            vis[edge[n][i]]++;
            a[n].num++;
            a[edge[n][i]].pre = n;
            dfs(edge[n][i], dep+1);
        }
    }
}

void solve()
{
    int n, k;
    scanf("%d%d", &n, &k);

    init(n);    //每个cas都需要初始化

    for(int i=0; i<n-1; i++)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        edge[v].push_back(u);
        edge[u].push_back(v);
    }

    dfs(1, 1);   //build the tree

    for(int i=0; i<k; i++)
    {
        s.clear();
        memset(vis, 0, sizeof vis);  //标记是否需要重读 a[i].num
        int m, p;
        scanf("%d", &m);
        int cnt = n-m;    // important nodes
        Node now;
        for(int i=0; i<m; i++)
        {
            scanf("%d", &p);
            now = a[p];
            s.insert(now);
        }

        for(set<Node>::iterator it=s.begin(); it!=s.end(); it++)
        {
            //printf("##%d %d %d\n", (*it).id, a[(*it).id].val, cnt);
            if(!vis[(*it).id]){      // not valued
                a[(*it).id].val = a[(*it).id].num;
                vis[(*it).id] = 1;
            }

            if(a[(*it).id].val == 0){   // 当前分支无贡献
                if(!vis[(*it).pre]){
                    a[(*it).pre].val = a[(*it).pre].num;
                    vis[(*it).pre] = 1;
                }
                a[(*it).pre].val--;
            }

            else if(a[(*it).id].val == 1);  // 当前分支对父亲节点有贡献(当前分支下有一个important node)

            else if(a[(*it).id].val >= 2){  // 当前节点下的分支有两个以上贡献,当前节点可以加入集合cnt++.

                cnt++;                   // unimportant into set
            }
        }

        printf("%d\n", cnt);
    }
}

int main()
{
    int T;
    scanf("%d", &T);
    for(int cas=1; cas<=T; cas++)
    {
        printf("Case #%d:\n", cas);

        solve();
    }

    return 0;
}

D - Coconuts

 

TanBig, a friend of Mr. Frog, likes eating very much, so he always has dreams about eating. One day, TanBig dreams of a field of coconuts, and the field looks like a large chessboard which has R rows and C columns. In every cell of the field, there is one coconut. Unfortunately, some of the coconuts have gone bad. For sake of his health, TanBig will eat the coconuts following the rule that he can only eat good coconuts and can only eat a connected component of good coconuts one time(you can consider the bad coconuts as barriers, and the good coconuts are 4-connected, which means one coconut in cell (x, y) is connected to (x - 1, y), (x + 1, y), (x, y + 1), (x, y - 1). 

Now TanBig wants to know how many times he needs to eat all the good coconuts in the field, and how many coconuts he would eat each time(the area of each 4-connected component). 
InputThe first line contains apositiveinteger T( T10) which denotes the test cases. T test cases begin from the second line. In every test case, the first line contains two integers R and C,  0<R,C109 the second line contains an integer n, the number of bad coconuts,  0n200 from the third line, there comes n lines, each line contains two integers,  xixi and  yiyi, which means in cell( xi,yixi,yi), there is a bad coconut. 

It is guaranteed that in the input data, the first row and the last row will not have bad coconuts at the same time, the first column and the last column will not have bad coconuts at the same time. 
OutputFor each test case, output "Case #x:" in the first line, where x denotes the number of test case, one integer k in the second line, denoting the number of times TanBig needs, in the third line, k integers denoting the number of coconuts he would eat each time, you should output them in increasing order.Sample Input
2

3 3
2
1 2
2 1

3 3
1
2 2
Sample Output
Case #1:
2
1 6
Case #2:
1
8

D题:给出一个1e9*1e9的图,然后给出200个坏点,问由好点组成的四连通块的个数,并且按照升序输出这些联通块的大小。

D题看到坏点这么多好点这么少,第一反应就是用坐标离散化去求解。在学习了挑战上的坐标离散化之后就手码了一发,保留所有坏点来保证坏点包围的联通块大小是准确的,然后判断如果一个联通块四周都能达到边界则这个联通块没有被坏点包围,那么就用总点数-坏点点数-坏点包围的好点点数来求出最大联通块的值,但是这个解法有很多的bug。

之后查了关于坐标离散化的一些内容,其实感觉什么重要的都没有看到,但是想到了既然我们将原本来的坐标映射到了一个离散化之后的图上,那我们同样可知离散化后图上的点,对于原图的映射。此时我们就可以知道,当前这一格,代表着原来的多少格(其实是将行和列分别储存,第i行代表原来多少行,第j列代表原来多少列,然后mp[i][j]这一点对应原来多少点就求出来了)。我们认为的规定离散化去掉的点的值赋给左边,那么我们再特判一下第一行和第一列就可以了。

#include<bits/stdc++.h>
#define LL long long

using namespace std;

const int maxn = 205;

int x[maxn], y[maxn], xx[6*maxn], yy[6*maxn];    ///x, y用于存储对应点的坐标
                                                ///xx yy 用于存放离散化之后的行列所对应的原行数
int tox[] = {0, -1, 0, 1};
int toy[] = {1, 0, -1, 0};
bool mp[6*maxn][6*maxn];                         ///用于存放离散化之后的图

int n, w, h;

int LSH(int *x, int* xx, int R)
{
    vector<int >xs;
    for(int i=0; i<n; i++)
        for(int d=-1; d<=1; d++)
            if(x[i]+d>0 && x[i]+d<=R)
                xs.push_back(x[i]+d);                                  ///将对应坐标本身和左右读入到xs中,即xs中储存的是我们所有需要保留的坐标值

    sort(xs.begin(), xs.end());                                         ///先sort才能用unique
    xs.erase(unique(xs.begin(), xs.end()), xs.end());                   ///unique将区间中重复的元素放到数组的最后部分,并返回第一个重复元素的指针(迭代器)
                                                                        ///然后用erase删去重复部分,即xs中按照升序存放了所有要用到的坐标,而xs的下标就是离散化之后对应的坐标
    for(int i=0; i<n; i++){
        int sign = find(xs.begin(), xs.end(), x[i]) - xs.begin() + 1;    ///新的下标  [1, xs.size()]                                          
        x[i] = sign;                                                     ///x[i]对应到新的下标
    }

    for(int i=0; i<xs.size(); i++){                                      ///新的下标所对应的原值,用于判断离散化后节点对应的权值
        xx[i+1] = xs[i];
    }

    xx[0] = 0;                                                           ///最小边界为0
    xx[xs.size()+1] = R+1;                                               ///最大行为R+1行

//    for(int i=0; i<=xs.size()+1; i++)
//        printf("%d%c", xx[i], i==xs.size()+1?'\n':' ');
//
//    for(int i=1; i<=xs.size(); i++)
//        printf("%d%c", xx[i+1]-xx[i-1]-1, i==xs.size()?'\n':' ');

    return xs.size();
}

LL bfs(int x, int y)
{
    LL cnt = 0;
    queue<pair<int, int> >q;
    q.push(make_pair(x, y));
    mp[x][y] = true;
    while(!q.empty())
    {
        int nowx = q.front().first, nowy = q.front().second;
        q.pop();

        LL x1 = nowx==1?xx[nowx+1]-xx[nowx-1]-1:xx[nowx+1]-xx[nowx];    ///将省略部分全部给了较小的一行(列)所以要对第一行(列)进行特殊处理
        LL y1 = nowy==1?yy[nowy+1]-yy[nowy-1]-1:yy[nowy+1]-yy[nowy];
        cnt += x1*y1;                          ///cnt加上当前单元格所代表的行列乘积

        for(int i=0; i<4; i++)
        {
            int nextx = nowx + tox[i];
            int nexty = nowy + toy[i];
            if(nextx>0 && nexty>0 && nextx<=w && nexty<=h && !mp[nextx][nexty])
            {
                q.push(make_pair(nextx, nexty));
                mp[nextx][nexty] = true;
            }
        }
    }

    return cnt;
}

int main()
{
    int T, cas = 1, R, C;
    scanf("%d", &T);
    while(T--)
    {
        vector<LL >ans;

        memset(mp, false, sizeof(mp));

        scanf("%d%d", &R, &C);
        scanf("%d", &n);

        if(n==0){
            printf("Case #%d:\n", cas++);
            printf("1\n");
            printf("%lld\n", (LL)R*(LL)C);
            continue;
        }

        for(int i=0; i<n; i++){
            scanf("%d%d", &x[i], &y[i]);
        }

        w = LSH(x, xx, R);
        h = LSH(y, yy, C);

        for(int i=0; i<n; i++)
            mp[x[i]][y[i]] = true;

        for(int i=1; i<=w; i++)
            for(int j=1; j<=h; j++)
            {
                if(mp[i][j]) continue;

                LL temp = bfs(i, j);
                ans.push_back(temp);
            }

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

        printf("Case #%d:\n", cas++);
        printf("%d\n", (int)ans.size());
        for(int i=0; i<ans.size(); i++)
        {
            printf("%lld%c", ans[i], i==ans.size()-1?'\n':' ');
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值