这道题我临场想到了枚举菱形的起点和终点,然后每次枚举起点指向的点,每个指向的点再枚举它指向的点看有没有能到终点的,有一条就把起点到终点的路径个数加1,最后ans+=C(路径总数,2)。每两个点都这么弄。但是我考虑时间复杂度n2前面的系数过大会超时,再想别的方法也没想出来。。

其实思路就是这样的,只不过时间上可以优化一下,就是用常用的两种做法不变而优化时间复杂度的方法:1.以空间换时间2.分步降维

#include <cstdio>
#include <vector>

using namespace std;

const int maxn = 3000 + 10;
bool G[maxn][maxn];
vector<int> nxt[maxn];

int main()
{
    //freopen("in.txt", "r", stdin);
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 0; i < m; ++i)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        G[a][b] = true;
        nxt[a].push_back(b);
    }

    int ans = 0;
    for(int a = 1; a <= n; ++a)
        for(int c = 1; c <= n; ++c)
        {
            if(a != c)
            {
                int r = 0;
                for(int b = 0; b < nxt[a].size(); ++b)
                {
                    if(nxt[a][b] != a && nxt[a][b] != c && G[nxt[a][b]][c])
                        r++;
                }
                ans += r*(r-1)/2;
            }
        }

    printf("%d\n", ans);

    return 0;
}
以空间换时间

相关文章: