bestcoder round 73 div2

Rikka with Chess

 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,至于这个结论的证明,sorry,I can't.

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int t,n,m;
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        cout<<n/2+m/2<<endl;
    }
    return 0;
}

Rikka with Graph

 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
这里有一个重要的图论性质,一个有n个顶点的图,要使其联通,必须要有n-1条边,所以我们最多只能删两条,最少删一条,那么我们就可以用n^2来枚举删掉的边,但是怎么判断其是否联通呢?我是一开始预处理出一个邻接矩阵(>0可以到,=0不能到,因为可能有重边),然后每次枚举的时候减掉相应的,再从1开始,广搜一下,只要队列长度=n就可以了。但在BFS中,还有一个细节,不能for i:=1 to n do来枚举与当前队列点相连的节点,而应该用正向表(我叫它儿子表示法),一开始就记录一下哪些点是某个点可以达到的,然后广搜中枚举它的所有儿子即可。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int a[105],b[105],p[105],g[105],son[105];
int f[105][105],s[105][105];
int tt,t,w,n,ans;
int main()
{
    cin>>tt;
    while(tt--)
    {
        cin>>n;
        ans=0;
        memset(f,0,sizeof(f));
        memset(son,0,sizeof(son));
        for(int i=1;i<=n+1;i++)
        {
            cin>>a[i]>>b[i];
            f[a[i]][b[i]]++;
            f[b[i]][a[i]]++;
            son[a[i]]++;
            son[b[i]]++;
            s[a[i]][son[a[i]]]=b[i];
            s[b[i]][son[b[i]]]=a[i];
        }
        for(int i=1;i<=n+1;i++)
        for(int j=1;j<=n+1;j++)
        if(i<=j)
        {
            memset(p,0,sizeof(p));
            f[a[i]][b[i]]--;
            f[b[i]][a[i]]--;
            if(i!=j)
            {
                f[a[j]][b[j]]--;
                f[b[j]][a[j]]--;
            }
            int t=0;
            int w=1;
            g[1]=1;
            p[1]=1;
            while(t<w)
            {
                t++;
                for(int k=1;k<=son[g[t]];k++)
                {
                    int id=s[g[t]][k];
                    if(f[g[t]][id]>=1&&p[id]==0)
                    {
                        w++;
                        g[w]=id;
                        p[id]=1;
                    }
                }
            }
            if(t==n) ans++;
            f[a[i]][b[i]]++;
            f[b[i]][a[i]]++;
            if(i!=j)
            {
                f[a[j]][b[j]]++;
                f[b[j]][a[j]]++;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}


你可能感兴趣的:(C++,bfs,noip)