题目:https://www.luogu.org/problemnew/show/P4017
由于这个题有严格的偏序关系(应该严格吧)。明显就可以想到拓扑排序。
用吃与被吃建图。同时记录出度与入度。
求拓扑排序的同时。如果谁的出度为 0 。则证明这条链到头。ans++。
最后输出答案。
代码如下:
这是邻接表存图的,速度比较快。
#include<bits/stdc++.h> #define sc(x) scanf("%d",&x) using namespace std; const int mod=80112002; struct edge{ int from,to,nxt; }t[5000005]; int n,m,du[5005],chu[5005],f[5005],ans,head[5005]; queue<int> q; inline void topo() { for(int i=1;i<=n;i++) if(du[i]==0) q.push(i),f[i]=1; while(!q.empty()){ int now=q.front(); q.pop(); for(int i=head[now];i;i=t[i].nxt){ int tt=t[i].to; f[tt]+=f[now]; f[tt]%=mod; du[tt]--; if(du[tt]==0){ if(chu[tt]==0){ ans+=f[tt]; ans%=mod; } q.push(tt); } } } } int main() { sc(n),sc(m); int tot=0; while(m--){ int a,b; sc(a),sc(b); t[++tot].from=a;t[tot].to=b;t[tot].nxt=head[a]; head[a]=tot; du[b]++;chu[a]++; } topo(); cout<<ans<<endl; // system("pause"); return 0; }
然而最一开始我写的是vector的,感觉写的比较短,不用管那么多。
代码如下:
#include<bits/stdc++.h> #define sc(x) scanf("%d",&x) using namespace std; const int mod=80112002; struct edge{ int from,to; edge() {} edge(int _from,int _to): from(_from),to(_to) {} }; vector<edge> g[5000005]; int n,m,du[5005],chu[5005],f[5005],ans; queue<int> q; inline void topo() { for(int i=1;i<=n;i++) if(du[i]==0) q.push(i),f[i]=1; while(!q.empty()){ int now=q.front(); q.pop(); for(vector<edge>::iterator it=g[now].begin();it!=g[now].end();it++){ int t=it->to; f[t]+=f[now]; f[t]%=mod; du[t]--; if(du[t]==0){ if(chu[t]==0){ ans+=f[t]; ans%=mod; } q.push(t); } } } } int main() { sc(n),sc(m); while(m--){ int a,b; sc(a),sc(b); g[a].push_back(edge(a,b)); du[b]++;chu[a]++; } topo(); cout<<ans<<endl; // system("pause"); return 0; }
这个时空比较爆炸。
但是感觉还是挺好写的(滑稽)。