5328. 【NOIP2017提高A组模拟8.22】世界线

(File IO): input:worldline.in output:worldline.out

Time Limits: 1500 ms Memory Limits: 262144 KB

Description

JZOJ 5328. 【NOIP2017提高A组模拟8.22】世界线-LMLPHP

Input

JZOJ 5328. 【NOIP2017提高A组模拟8.22】世界线-LMLPHP

Output

JZOJ 5328. 【NOIP2017提高A组模拟8.22】世界线-LMLPHP

Sample Input

5 5

1 2

1 3

2 3

3 4

4 5

Sample Output

5

Data Constraint

JZOJ 5328. 【NOIP2017提高A组模拟8.22】世界线-LMLPHP

Hint

样例解释

JZOJ 5328. 【NOIP2017提高A组模拟8.22】世界线-LMLPHP

题解

不难发现,题目要求的就是每一个点到能到的点数减去已有的边数

直接暴力肯定不行

所以用bitset优化一下就好啦,维护每个点能到的点

代码

#include<cstdio>
#include<vector>
#include<bitset>
#define BITSET 30000
#define N 60010
using namespace std; vector<long>out[N];
bitset<BITSET+10>a[N];
long in[N],b[N]; int main()
{ long n,m,x,y,i,j,to,tot,l,r;
long long ans=0;
freopen("worldline.in","r",stdin);
freopen("worldline.out","w",stdout);
scanf("%ld%ld",&n,&m);
for(i=1;i<=m;i++){
scanf("%ld%ld",&x,&y);
out[x].push_back(y);
in[y]++;
}
tot=0;
for(i=1;i<=n;i++)
if(!in[i])
b[++tot]=i;
for(i=1;i<=tot;i++)
for(j=0;j<out[b[i]].size();j++){
to=out[b[i]][j];
if(--in[to]==0)
b[++tot]=to;
}
for(l=1,r=BITSET;l<=n;l=r+1,r+=BITSET){
for(i=1;i<=n;i++)
a[i].reset();
for(i=n;i>=1;i--){
for(j=0;j<out[b[i]].size();j++){
to=out[b[i]][j];
a[b[i]]|=a[to];
}
ans+=a[b[i]].count();
if(b[i]>=l&&b[i]<=r)
a[b[i]][b[i]-l]=1;
}
}
printf("%lld\n",ans-m);
return 0;
}
05-08 15:42