2 条题解
-
0

// SCC 缩点 Tarjan 算法 O(N) #include<bits/stdc++.h> #define ll long long using namespace std; const int N=100010; vector<int> e[N],ee[N]; int n,m,mod; int dfn[N],low[N],stk[N],top,scc[N],siz[N],cnt; int d[N],f[N],mx,sum; void tarjan(int x){ //SCC缩点 dfn[x]=low[x]=++dfn[0]; stk[++top]=x; for(auto y:e[x]){ if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]); else if(!scc[y]) low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]){ ++cnt; while(stk[top+1]!=x) scc[stk[top--]]=cnt,siz[cnt]++; } } int main(){ scanf("%d%d%d",&n,&m,&mod); for(int a,b;m--;) scanf("%d%d",&a,&b),e[a].push_back(b); for(int i=1; i<=n; i++)if(!dfn[i]) tarjan(i); //SCC缩点 unordered_set<ll> S; //哈希表判重边 for(int x=1; x<=n; x++)for(auto y:e[x]){ //枚举每个点的邻接点 int a=scc[x],b=scc[y]; ll hash=a*1000000ll+b; //端点的哈希值 if(a!=b && !S.count(hash)){ //不在一个SCC且边(a,b)没被加过 ee[a].push_back(b); //缩点之间连边 S.insert(hash); //记录哈希值 } } for(int x=cnt; x; x--){ //枚举缩点 if(d[x]==0){ //拓扑图起点 d[x]=siz[x]; mx=max(mx,d[x]); f[x]=1; } for(auto y:ee[x]){ //枚举邻接点 if(d[y]<d[x]+siz[y]){ d[y]=d[x]+siz[y]; //更新最长路 mx=max(mx,d[y]); f[y]=f[x]; //继承方案数 } else if(d[y]==d[x]+siz[y]){ f[y]=(f[y]+f[x])%mod; //更新方案数 } } } for(int i=1; i<=cnt; i++) //枚举缩点 if(d[i]==mx) sum=(sum+f[i])%mod; //累加最长路的方案数 printf("%d\n%d\n",mx,sum); } -
0
#include <bits/stdc++.h> using namespace std; const int N=110000; vector<int> G1[N], G2[N]; int tsp, cnt, low[N], dfn[N], scc[N], num[N]; stack<int> stk; bool instk[N]; void tarjan(int x) { dfn[x] = low[x] = ++tsp; stk.push(x); instk[x] = 1; for(int y : G1[x]) { if(dfn[y] == 0) { tarjan(y); low[x] = min(low[x], low[y]); } else if(instk[y]) low[x] = min(low[x], dfn[y]); } if(low[x] == dfn[x]) { cnt++; for(int z = -1; z != x;) { z = stk.top(); stk.pop(); instk[z] = 0; scc[z] = cnt; num[cnt]++; } } } int main() { int n, m, X; scanf("%d%d%d", &n, &m, &X); memset(G1, 0, sizeof(G1)); for(int i=1, x, y; i <= m; i++) scanf("%d%d", &x, &y), G1[x].push_back(y); tsp = cnt = 0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(instk,0,sizeof(instk)); memset(scc,0,sizeof(scc)); memset(num,0,sizeof(num)); for(int i=1; i <= n; i++) if(dfn[i] == 0) tarjan(i); map<pair<int, int>, bool> mp; vector<int> rd(cnt + 1); for(int i=1; i <= n; i++) for(int j : G1[i]) { int x = scc[i], y = scc[j]; if(x != y && !mp[{x, y}]) G2[x].push_back(y), rd[y]++, mp[{x, y}] = true; } vector<int> d(cnt + 1), C(cnt + +1);; for(int i=1; i <= cnt; i++) d[i] = num[i], C[i] = 1; deque<int> q; for(int i=1; i <= cnt; i++) if(rd[i] == ) q.push_back(i); while(!q.empty()) { int x = q.front(); q.pop_front(); for(int y : G2[x]) { rd[y]--; if(rd[y] == 0) q.push_back(y); if(d[y] < d[x] + num[y]) d[y] = d[x] + num[y], C[y] = C[x]; else if(d[y] == d[x] + num[y]) C[y] = (C[y] + C[x]) % X; } } int maxd = 0; for(int i=1; i <= cnt; i++) maxd = max(maxd, d[i]); int ansC = 0; for(int i=1; i <= cnt; i++) if(maxd == d[i]) ansC = (ansC + C[i]) % X; printf("%d\n%d\n", maxd, ansC); return 0; }
- 1
信息
- ID
- 2746
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 113
- 已通过
- 25
- 上传者