rt,复制一层图,然后在两层图中间连原图的反向边,表示一次逆行。
然而我发现边权不好搞。因为你分层之后可能会有点重复贡献。所以怎么去重?
以为我 SPFA 假了,调了好久,现在发现这个问题之后大脑直接宕机了。求大佬调。
#include<bits/stdc++.h>
using namespace std;
int n,m;
vector<int> org[100050];
stack<int> que;
bitset<100050> inque;
int dtot = 0,stot = 0,dfn[100050],low[100050],id[100050];
int Size[100050];
void tarjan(int now){
dfn[now] = low[now] = ++dtot;
que.push(now);
inque[now] = 1;
for(auto i:org[now]){
if(!dfn[i]){
tarjan(i);
low[now] = min(low[now],low[i]);
}else if(inque[i]){
low[now] = min(low[now],dfn[i]);
}
}
if(dfn[now] == low[now]){
int y;
stot++;
do{
y = que.top();
que.pop();
inque[y] = 0;
id[y] = stot;
Size[stot]++;
}while(y != now);
}
return;
}
int etot = 0,Last[200050],Next[300050],End[300050];
void addedge(int u,int v){
// printf("!%d %d\n",u,v);
etot++;
Next[etot] = Last[u];
Last[u] = etot;
End[etot] = v;
return;
}
namespace spfa{
int dis[200050];
bitset<200050> inque;
queue<int> que;
void spfa(){
memset(dis,-0x3f,sizeof(int)*((stot<<1)+10));
inque.reset();
while(que.size()){
que.pop();
}
dis[id[1]] = Size[id[1]];
que.push(id[1]);
inque[id[1]] = 1;
int now;
while(que.size()){
now = que.front();
que.pop();
inque[now] = 0;
for(int i = Last[now]; i; i = Next[i]){
if(dis[End[i]] < dis[now]+Size[End[i]]){
dis[End[i]] = dis[now]+Size[End[i]];
if(inque[End[i]]){
continue;
}
que.push(End[i]);
inque[End[i]] = 1;
}
}
}
return;
}
}
using spfa::dis;
int main(){
scanf("%d%d",&n,&m);
while(m--){
static int tpa,tpb;
scanf("%d%d",&tpa,&tpb);
org[tpa].push_back(tpb);
}
for(int i = 1; i <= n; i++){
if(!dfn[i]){
tarjan(i);
}
}
for(int i = 1; i <= stot; i++){
Size[i+stot] = Size[i];
}
for(int i = 1; i <= n; i++){
for(auto j:org[i]){
if(id[i] != id[j]){
addedge(id[i],id[j]);
addedge(id[i]+stot,id[j]+stot);
addedge(id[j],id[i]+stot);
}
}
}
if(stot == 1){
printf("%d",Size[1]);
return 0;
}
spfa::spfa();
printf("%d",max(dis[id[1]+stot],dis[id[1]]));
return 0;
}