做法:Tarjan 记录scc 然后根据SCC去重新建图
| #include <cstdio> |
| #include <stack> |
| #include <algorithm> |
| #include <iostream> |
| #include <cstring> |
| #include <vector> |
| #include <queue> |
| #define ep emplace_back |
| |
| #define lld long long |
| #define ios std::ios::sync_with_stdio(false);std::cin.tie(0); |
| #define vec vector |
| const int N = 4e5+9; |
| |
| const int INF = 0x7FFFFFFF; |
| |
| const int inf1 = 0x3f3f3f3f; |
| const int inf2 = 0x7f7f7f7f; |
| |
| using namespace std; |
| |
| int head[N], idx = 0; |
| bool vis[N]; |
| struct node { |
| int to, val, next; |
| }; |
| node e[N]; |
| int n, m; |
| int time_ = 0; |
| stack<int> st; |
| int low[N], dfn[N]; |
| int scc[N], scc_cnt = 0; |
| int a[N], p[N], in[N]; |
| lld ans = 0,dist[N]; |
| int din[N]; |
| void add(int u, int v, int val) { |
| e[idx] = {v, val, head[u]}; |
| head[u] = idx++; |
| } |
| node ee[N]; |
| int idx__=0,head__[N]; |
| void add__(int u,int v,int val){ |
| ee[idx__] = {v,val,head__[u] }; |
| head__[u] = idx__++; |
| } |
| void bd() { |
| cin >> n >> m; |
| memset(head, -1, sizeof(head)); |
| memset(head__, -1, sizeof(head__)); |
| |
| |
| for (int i = 1; i <= m; ++i) { |
| int u, v; |
| cin >> u >> v; |
| add(u, v,0); |
| } |
| } |
| |
| void tarjan(int u) { |
| low[u] = dfn[u] = ++time_; |
| vis[u] = true; |
| st.push(u); |
| for (int i = head[u]; i != -1; i = e[i].next) { |
| int v = e[i].to; |
| if (dfn[v] == 0) { |
| tarjan(v); |
| low[u] = min(low[u], low[v]); |
| } else if (vis[v]) { |
| |
| low[u] = min(low[u], dfn[v]); |
| |
| } |
| } |
| |
| if (low[u] == dfn[u]) { |
| |
| ++scc_cnt; |
| while (true) { |
| int v = st.top(); |
| st.pop(); |
| vis[v] = false; |
| scc[v] = scc_cnt; |
| p[scc_cnt] += a[v]; |
| if (v == u) break; |
| } |
| } |
| } |
| |
| void debug(){ |
| |
| for(int i=1 ; i<=n ; ++i) |
| cout<<scc[i]<<"\n"; |
| |
| } |
| void bd__() { |
| for (int i = 1; i <= n; ++i) { |
| for (int u = head[i]; u != -1; u = e[u].next) { |
| int v = e[u].to; |
| |
| int scc_u = scc[i]; |
| int scc_v = scc[v]; |
| if (scc_u != scc_v) { |
| |
| add__(scc_u, scc_v, 0); |
| din[scc_v]++; |
| } |
| } |
| } |
| } |
| int main() { |
| ios; |
| bd(); |
| for (int i = 1; i <= n; ++i) |
| if (!dfn[i]) tarjan(i); |
| |
| bd__(); |
| |
| return 0; |
| } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析