
这道题我临场想到了枚举菱形的起点和终点,然后每次枚举起点指向的点,每个指向的点再枚举它指向的点看有没有能到终点的,有一条就把起点到终点的路径个数加1,最后ans+=C(路径总数,2)。每两个点都这么弄。但是我考虑时间复杂度n2前面的系数过大会超时,再想别的方法也没想出来。。
其实思路就是这样的,只不过时间上可以优化一下,就是用常用的两种做法不变而优化时间复杂度的方法:1.以空间换时间2.分步降维
#include <cstdio>
#include <vector> using namespace std; const int maxn = + ;
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 = ; i < m; ++i)
{
int a, b;
scanf("%d%d", &a, &b);
G[a][b] = true;
nxt[a].push_back(b);
} int ans = ;
for(int a = ; a <= n; ++a)
for(int c = ; c <= n; ++c)
{
if(a != c)
{
int r = ;
for(int b = ; b < nxt[a].size(); ++b)
{
if(nxt[a][b] != a && nxt[a][b] != c && G[nxt[a][b]][c])
r++;
}
ans += r*(r-)/;
}
} printf("%d\n", ans); return ;
}
以空间换时间
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<cctype>
#include<sstream>
using namespace std;
#define pii pair<int,int>
#define LL long long int
const int eps=1e-;
const int INF=;
const int maxn=+;
vector<int>v[maxn];
int n,m,a,b,num[maxn][maxn],ans=;
int main()
{
//freopen("in8.txt","r",stdin);
//freopen("out.txt","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<m;i++)
{
scanf("%d%d",&a,&b);
v[a].push_back(b);
}
for(int i=;i<=n;i++)
{
int si=v[i].size();
for(int j=;j<si;j++)
{
int t=v[i][j];
int st=v[t].size();
for(int k=;k<st;k++)
{
num[i][v[t][k]]++;
}
}
}
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
if((i!=j)&&(num[i][j]>))
{
ans+=(num[i][j]-)*num[i][j]/;
}
}
}
printf("%d\n",ans);
//fclose(stdin);
//fclose(stdout);
return ;
}
分步降维