codeforces 498D Unbearable Controversy of Being (暴力乱搞)

传送门:点击打开链接

题目大意:

定义下图为“damn rhombus”,给定一个有向图,求出有多少个“damn
rhombus”。

解题思路1:

分析可以得出其实“damn rhombus”的意思就是求a->c通过2个节点中转的个数。也就是说 如果a->c中间中转了x个点,那么对于点对(a,c)来说“damn
rhombus”就有C(x,2)个。

那么通过层数为2的bfs就可以得出答案。

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define INF 0x7f7f7f7f
#define maxn 3010
#define maxm 30010
using namespace std;
struct Edge
{
    int to;
    int next;
}es[maxm];
int cnt,p[maxn];
int used[maxn];
int n,m;

void add(int x,int y)
{
    es[cnt].to = y;
    es[cnt].next = p[x];
    p[x] = cnt++;

}
long long bfs(int x)
{
    memset(used,0,sizeof used);
    queue <int > q;
    for(int i = p[x];i+1;i = es[i].next)
     q.push(es[i].to);
    while(!q.empty())
    {
        int t = q.front();
        q.pop();
        for(int i = p[t];i+1;i = es[i].next)
        if(es[i].to != x) used[es[i].to]++;
    }
    long long res = 0;
    for(int i = 1;i <= n;i++) if(used[i] >= 2) res += (used[i]-1)*used[i]/2;
    return res;
}

int main()
{
    scanf("%d %d",&n,&m);

    memset(p,-1,sizeof p);
    for(int i = 0;i < m;i++)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        add(x,y);
    }
    long long ans = 0;
    for(int i = 1;i <= n;i++)
    {
        ans += bfs(i);
    }
    printf("%d\n",ans);

    return 0;
}

解题思路2:

我在比赛的时候想到了一个很奇葩的做法。虽然被上面的代码skipped了。但是事实上是可以过的。悲伤的表情。

构造矩阵A。
A[i][j]表示从i->j不经过中转的路径数目。

那么学过线性代数的都知道,这个矩阵自乘的结果其实就是a[i][j]表示i->j经过一次中转的路径条数。只需要加一个优化就居然可以让O(n3)的代码过掉。

真的代码不要太短。

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
long long  a[3010][3010];
long long res[3010][3010];
int n,m;
int main()
{
    scanf("%d %d",&n,&m);
    for(int i = 0;i < m;i++)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        a[x][y]++;
    }
    for(int k = 1;k <= n;k++)
        for(int i = 1;i <= n;i++)
        {
            if(a[i][k] == 0) continue;//优化
            for(int j = 1;j <= n;j++)
                res[i][j] += a[i][k]*a[k][j];
        }
    long long ans = 0;
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= n;j++)
        {
            if(i == j) continue;
            ans += (res[i][j]*(res[i][j]-1))/2;
        }
    printf("%d\n",ans);
    return 0;
}
时间: 2024-10-09 08:21:19

codeforces 498D Unbearable Controversy of Being (暴力乱搞)的相关文章

topcoder-srm610-div2-550(暴力乱搞)

给你一个01矩阵,求其中最大的01交替的矩阵 由于n最大才100,所以直接暴力乱搞 先求出第i行,所有列往上的合法长度,然后枚举以第j列为最左边的列,计算可以得到的最大矩阵 /************************************************************************* > File Name: 2.cpp > Author: ALex > Mail: [email protected] > Created Time: 2015年

Codeforces 484(#276 Div 1) A Bits 乱搞

题意:给你一个非负整数范围,求其中二进制中 1 最多且数字最小的数 解题思路:乱搞,找到两个数第一个不匹配的位数,将后面的位都赋值为1(如果右端点这位本身就是1,则从这一位开始), 解题代码: 1 // Author: darkdream 2 // Created Time: 2014年11月06日 星期四 00时24分10秒 3 4 #include<vector> 5 #include<list> 6 #include<map> 7 #include<set&

Codeforces Gym 100203G Good elements 暴力乱搞

原题链接:http://codeforces.com/gym/100203/attachments/download/1702/statements.pdf 题解 考虑暴力的复杂度是O(n^3),所以我们需要记录所有的ai+aj,如果当前考虑到了ak,那么就去前面寻找ai,使得ak-ai是我们记录过的和.整个算法的复杂度O(n^2). 代码 #include<iostream> #include<cstring> #include<cstdio> #include<

CodeForces 489D Unbearable Controversy of Being

题意: n(3000)个点m(30000)条边的有向简单图  统计题目中所画的菱形数目 思路: 我们将菱形可以看作a->c点距离为2的两条路  那么假设我们枚举i j两点同时知道i->j距离为2的路径条数  就可以用简单的组合数计算 如果暴力计算路径条数则是n^3的  不过我们可以利用距离为2这个特点  我们同时用邻接表和邻接矩阵存储图  通过邻接表枚举所有边m  这时知道i->k距离为1  那么我们再枚举所有n个点  邻接矩阵判断如果k->j有路  则i->j有长度2的路径

BNUOJ 39423 暴力乱搞

最有的答案肯定是找到一些点的集合,这些点两两之间是朋友关系. 考虑到n,m比较小,这样的集合最多只有14个点,暴力找点的集合 先找出1 个点的集合,有n个这样的集合 然后找出2个点的集合,找的时候要求编号比之前的大,这样就能保证不重不漏 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cctype> #include<cmath&

POJ 3077-Rounders(水题乱搞)

Rounders Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7697   Accepted: 4984 Description For a given number, if greater than ten, round it to the nearest ten, then (if that result is greater than 100) take the result and round it to th

CodeForces - 1228D (暴力+思维+乱搞)

题意 https://vjudge.net/problem/CodeForces-1228D 有一个n个顶点m条边的无向图,在一对顶点中最多有一条边. 设v1,v2是两个不相交的非空子集,当满足以下条件时f(v1,v2)为真 v1中的点之间不存在边 v2中的点之间不存在边 对于在v1v2中的每一对顶点,x在v1中,y在v2中,xy之间有边 所有点集不为空,且不相交,是否有v1,v2,v3使得f(v1,v2).f(v2,v3).f(v3,v1)均为真 如果有输出每个点所在的点集(1,2,3),否则

Codeforces 442B Kolya and Tandem Repeat(暴力)

题目连接:Codeforces 442B Kolya and Tandem Repeat 题目大意:给出一个字符串,可以再添加n个字符,问说可以找到SS的子串形式,S尽量长. 解题思路:枚举长度和起点判断即可,超过len的可以作为任意值,但是超过len+n就不行了. #include <cstdio> #include <cstring> const int N = 205; int n, len; char s[N]; bool judge (int l) { if (l <

CodeForces 398A Cards 贪心 暴力 瞎搞

搞了一晚上了快,各种YY乱搞啊,终于过了,一开始YY的都是错的,觉得 这道题目a,b的范围都是10^5,那就暴力枚举b被分成了几份,然后再继续YY,只用一个o去分隔x,这样最后剩下的o再集中在一起,也就是x的份数总是比o的份数多一份,也就是尽可能把x分开,尽可能把o集中在一块,前面都把x分开了,一个o分开两份x,后面还能有一大堆的o在一起,这样就满足了,然后又出错了,因为分成几份,有余数的,比如b = 6,你要分成4份,我以开始是分成 1  1  1  3这样子,这样不行,应该分成 1 1 2