题目描述
由于在某谷上举办的比赛反响热烈,参与人数众多,Jimmy 得到了一笔客观的广告费!于是,他决定来一场“说走就走的旅行”。
Jimmy 一共有 N 座想去的小岛,编号为 1⋯N。小岛之间一共有 M 班轮船,其中第 i 班轮船可以带 Jimmy 从第 xi 个小岛去第 yi 个小岛,但是 Jimmy 搭不了回程的轮船,因此他不能坐第 i 班轮船从第 yi 个小岛回到第 xi 个小岛。
在去之前 Jimmy 想做一个旅行计划。他可以选择从某个小岛开始旅行,途中搭船经过若干个其他的小岛(也可以不经过其他小岛),最后到达某个小岛并结束旅行。当然,Jimmy 也可以选择在一个小岛上一直度假,因此他的旅行可以在同一个岛上开始和结束。Jimmy 只关心旅行在哪开始以及在哪结束。他觉得,如果一个旅行计划的开始小岛或者结束小岛与其他的计划不同,那么这两个计划就算是不同的。
Jimmy 现在想知道他一共有多少种不同的旅行计划。你能帮帮他吗?
输入
第一行两个正整数 N,M,分别表示小岛的数量,以及轮船的班数。
接下来的 M 行,每行两个正整数 xi,yi,表示第 i 班轮船可以从第 xi 个小岛去到第 yi 个小岛。
输出
一行一个整数,表示不同的旅行计划种数。
样例数据
输入 #1 复制
3 3 1 2 2 3 3 2
输出 #1 复制
7
输入 #2 复制
3 0
输出 #2 复制
3
输入 #3 复制
4 4 1 2 2 3 3 4 4 1
输出 #3 复制
16
数据范围限制
对于 100% 的数据,满足:
- 1≤N≤2000
- 0≤M≤2000
- 1≤xi,yi≤N
- xi=yi
- 保证不存在完全相同的轮船班次,即 (xi,yi) 必定互不相同
提示
【样例 1 解释】
一共有 7 种不同的旅行计划,分别为 (1,1), (1,2), (1,3), (2,2), (2,3), (3,2), (3,3),其中 (p,q) 表示 Jimmy 从第 p 个小岛开始旅行,在第 q 个小岛结束。注意,由于 Jimmy 无法从第 2 个小岛前去第 1 个小岛,因此不存在 (2,1) 这种旅行方案。同理,也不存在 (3,1) 这种旅行方案。
【样例 2 解释】
Jimmy 没有任何轮船可以搭,他只能在同一个小岛上开始和结束旅行,一共有 3 个小岛,因此一共有 3 种不同的旅行方案。
【样例 3 解释】
Jimmy 可以在任意小岛上开始旅行、并在任意小岛上结束旅行,因此总的旅行方案数为 4 × 4 = 16 种。
代码:
#include <bits/stdc++.h>
using namespace std;
int ans=0,a[2001][2001],f[4001],w[2001][2001],num[2001],dis[2001],b[4001];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
w[x][y]=1;
a[x][++num[x]]=y;
}
for(int i=1;i<=n;i++)
{
int h=0,t=1;
memset(b,0,sizeof(b));
memset(f,0,sizeof(f));
for(int j=1;j<=n;j++) dis[j]=1e9+7;
dis[i]=0;
b[i]=1;
f[1]=i;
do
{
h++;
h=((h-1)%2001)+1;
int u=f[h];
b[u]=0;
for(int j=1;j<=num[u];j++)
{
if(dis[a[u][j]]>dis[u]+w[u][a[u][j]])
{
dis[a[u][j]]=dis[u]+w[u][a[u][j]];
if(b[a[u][j]]==0)
{
t++;
t=((t-1)%2001)+1;
f[t]=a[u][j];
b[a[u][j]]=1;
}
}
}
}while(h!=t);
for(int j=1;j<=n;j++)
{
if(dis[j]!=1e9+7)
{
ans++;
//printf("%d %d\n",i,j);
}
}
}
printf("%d",ans);
return 0;
}