BestCoder Round #73 (div.2) 总结

Rikka with Chess

 
 Accepts: 393
 
 Submissions: 548
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
一个n \times mn×m的黑白相间的棋盘,每次可以选择一个矩形把其中的所有格子反色。问把所有格子变成一种颜色时的最少操作次数。
输入描述
第一行一个整数 T(T \leq 10)T(T10) 表示数据组数。

每组数据有一行, 两个正整数 n,m(n \leq 10^9, m \leq 10^9)n,m(n109,m109)
输出描述
对于每组数据输出一行一个整数,代表最少需要的操作次数。
输入样例
3
1 2
2 2
3 3
输出样例
1
2

2

题解:

首先,如果先对偶数行取反,再对偶数列取反,可以得到一个[n/2] + [m/2][n/2]+[m/2](下取整)的解, 只要说明这个这是答案的下界就可以了。 考虑第一列,每次操作最多使得两个第一列的相邻元素变得一样, 第一列有n-1n1对相邻元素,这样使得第一列变成一样的次数就是[(n-1)/2][(n1)/2](上取整),同理考虑第一行即可。

#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
#define LL __int64
const LL maxm=1e3+10;
int main()
{
    LL t;
    scanf("%I64d",&t);
    while(t--)
    {
        LL m,n;
        scanf("%I64d%I64d",&m,&n);
        printf("%I64d\n",m/2+n/2);
    }
    return 0;
}

Rikka with Graph

 
 Accepts: 123
 
 Submissions: 525
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的:

给出一张 nn 个点 n+1n+1 条边的无向图,你可以选择一些边(至少一条)删除。

现在勇太想知道有多少种方案使得删除之后图依然联通。

当然,这个问题对于萌萌哒六花来说实在是太难了,你可以帮帮她吗?
输入描述
第一行一个整数表示数据组数 T(T \leq 30)T(T30)。

每组数据的第一行是一个整数 n(n \leq 100)n(n100)。

接下来 n+1n+1 行每行两个整数 u,vu,v 表示图中的一条边。
输出描述
对每组数据输出一行一个整数表示答案。
输入样例
1
3
1 2
2 3
3 1
1 3
输出样例
9
题解:让 nn 个点联通最少需要 n-1n1 条边,所以最多只能删除两条边,我们可以枚举删除的这两条边(或者唯一的一条边),然后暴力BFS判断连通性就好了。时间复杂度 O(n^3)O(n3)

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxm=1e3+10;
int u[maxm];
int v[maxm];
int p[maxm];
int find(int k)
{
    if(p[k]!=k)
        return p[k]=find(p[k]);
    else
        return p[k];
}
void Init()
{
    for(int i=1; i<=100; i++)
        p[i]=i;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0; i<n+1; i++)
        {
            scanf("%d%d",&u[i],&v[i]);
        }
        int sum=0;
        for(int i=0; i<n+1; i++)
        {
            Init();
            for(int k=0; k<n+1; k++)
            {
                if(k!=i)
                {
                    int x=find(u[k]);
                    int y=find(v[k]);
                    if(x!=y)
                        p[x]=y;
                }
            }
            int ans=0;
            for(int k=1; k<=n; k++)
            {
                if(find(k)!=find(1))
                {
                    ans=1;
                    break;
                }
            }
            if(ans==0)
                sum++;
        }
        for(int i=0; i<n+1; i++)
        {
            for(int j=i+1; j<n+1; j++)
            {
                Init();
                for(int k=0; k<n+1; k++)
                {
                    if(k==i||k==j)
                    {
                        continue;
                    }
                    int x=find(u[k]);
                    int y=find(v[k]);
                    if(x!=y)
                        p[x]=y;
                }
                int ans=0;
                for(int k=1; k<=n; k++)
                {
                    if(find(k)!=find(1))
                    {
                        ans=1;
                        break;
                    }
                }
                if(ans==0)
                    sum++;
            }
        }
        printf("%d\n",sum);
    }
    return 0;
}


你可能感兴趣的:(BestCoder Round #73 (div.2) 总结)