40pts,求调(tarjan+spfa)

P3387 【模板】缩点

检查过你的tarjan缩点没什么问题,但说实话不太清楚你那个SPFA在写什么,看似在跑SPFA,但实际上混入了什么入度,SPFA蛮跑不需要入度的啊?SPFA写法不应该是对每一个点跑一次最长路后取max吗。。。(离谱的是你似乎写的是跑最短路后取min?)总的而言这个SPFA我看得太迷糊了,提供一个拓扑排序加dp的写法吧,~~祝好~~
by 帝都_henry26268 @ 2023-11-07 16:51:25


@[Headofstate1945](/user/636409) ```cpp #include<iostream> #include<vector> #include<cstdio> #include<algorithm> #include<stack> #include<queue> #define ll long long using namespace std; const int MAXN = 1e4+10; const int MAXM = 1e5+10; int n,m; bool pd[MAXN][MAXN]; ll sum[MAXN]; int deg[MAXN]; queue<int> q; int out[MAXN]; ll dp[MAXN]; ll pt[MAXN]; int col[MAXN],vis[MAXN]; int dfn[MAXN],low[MAXN]; stack<int> st; int cnt=0,scc=0; //原始(人)图 vector<int> vct[MAXN]; //缩点后新图 vector<int> e[MAXN]; //dp时顺序图,新图的反图 vector<int> dpe[MAXN]; void Tarjan(int u){ cnt++;dfn[u] = cnt;low[u] = cnt; vis[u] = 1;st.push(u); for(int i = 0;i < vct[u].size();i++){ int v = vct[u][i]; if(!dfn[v]){ Tarjan(v); low[u] = min(low[u],low[v]); }else if(vis[v]){ low[u] = min(low[u],dfn[v]); } } if(dfn[u] == low[u]){ ++scc; //cout << u << " "; int tp; while(st.top() != u){ tp = st.top();st.pop(); col[tp] = scc;vis[tp] = 0; sum[scc] += pt[tp]; //cout << tp << " "; } //cout << endl; st.pop(); col[u] = scc;vis[u] = 0; sum[scc] += pt[u]; } return ; } int main(){ scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++) scanf("%lld",&pt[i]); for(int i = 1;i <= m;i++){ int u,v;scanf("%d%d",&u,&v); vct[u].push_back(v); //vct[v].push_back(u); } for(int i = 1;i <= n;i++){ if(!dfn[i]) Tarjan(i); } for(int u = 1;u <= n;u++){ for(int i = 0;i < vct[u].size();i++){ int v = vct[u][i]; if(col[u] != col[v] && !pd[col[u]][col[v]]){ //cout << col[u] << "-" << col[v] << endl; pd[col[u]][col[v]] = true; e[col[u]].push_back(col[v]); deg[col[v]]++; dpe[col[v]].push_back(col[u]); } } } //cout << scc << endl; for(int i = 1;i <= scc;i++){ if(!deg[i])q.push(i); } int t = 0; while(!q.empty()){ int u = q.front(); q.pop();out[++t] = u; for(int i = 0;i < e[u].size();i++){ int v = e[u][i]; deg[v]--; if(!deg[v]) q.push(v); } } for(int i = 1;i <= scc;i++){ int now = out[i]; dp[now] = sum[now]; for(int j = 0;j < dpe[now].size();j++){ int lst = dpe[now][j]; dp[now] = max(dp[now],dp[lst] + sum[now]); } } ll ans = 0; for(int i = 1;i <= scc;i++){ ans = max(ans,dp[i]); } printf("%lld\n",ans); return 0; } ```
by 帝都_henry26268 @ 2023-11-07 16:52:16


@[帝都_henry26268](/user/315655) 感谢你的帮助
by Headofstate1945 @ 2023-11-09 10:29:11


|