转换为邻接矩阵,题目要求的就很明了了,不能直接用bool或者int存,要用bitset,(支持位运算),但是空间不能直接开成maxn*maxn,会爆空间。

把原图分成两半做,开maxn*(maxn/2)就行了。

  上代码。

  

 1 #include<iostream>
 2 #include<bitset>
 3 #include<cstring>
 4 #include<vector>
 5 #define maxn 60005
 6 #define maxm 100005
 7 using namespace std;
 8 bitset<maxn/2>vis[maxn];
 9 int degi[maxn];
10 bool had[maxn];
11 int n,m,u,v,ans,mid;
12 bool flg;
13 int head[maxn],cnt;
14 struct EDGE{
15     int to,nxt;
16 }edge[maxm];
17 inline void read(int &x){
18     x=0;int f=1;char c=getchar();
19     while(!isdigit(c)){f=c=='-'?-1:1;c=getchar();}
20     while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
21     x=x*f;
22 }
23 inline void adde(int u,int v){
24     edge[++cnt].nxt=head[u],head[u]=cnt,edge[cnt].to=v;
25 }
26 inline void dfs(int x){
27     had[x]=1;
28     if(!flg){//如果当前求得是上一半的图
29         if(x<=mid) vis[x].set(x);
30     }
31     else{
32         if(x>mid) vis[x].set(x-mid);
33     }
34     for(register int i=head[x];i;i=edge[i].nxt){
35         int t=edge[i].to;
36         if(!had[t]) dfs(t);
37         vis[x]|=vis[t];
38     }
39 }
40 int main(){
41     freopen("worldline.in","r",stdin);
42     freopen("worldline.out","w",stdout);
43     read(n),read(m);
44     mid=n>>1;
45     for(register int i=1;i<=m;i++){
46         read(u),read(v);
47         adde(u,v);
48         degi[v]++;
49     }
50     for(register int i=1;i<=n;i++) if(!degi[i]) dfs(i);//找入度为0的点dfs能遍历整张有向无环图
51     for(register int i=1;i<=n;i++) ans+=vis[i].count(),vis[i].reset();
52     flg=1;//遍历下半张图
53     memset(had,0,sizeof(had));
54     for(register int i=1;i<=n;i++) if(!degi[i]) dfs(i);
55     for(register int i=1;i<=n;i++) ans+=vis[i].count();
56     printf("%d",ans-n-m);
57     return 0;
58 }
01-04 19:34