省选难度啊啊啊
经评论区的朋友提醒,代码已订正
先说一下该题思路:
首先,这题并非是求最短路,而是求最长路(最长路常用算法一般是拓扑排序,而我这个蒟蒻还没有学会QAQ)
但是这一题既然标签是连通图,那么肯定要用tarjan,考虑到缩点之后每个缩点都具有一定数量的点数,然后如果我们进入了这个缩点,那么我们可以从进入该缩点的点起,然后将整个缩点中的点全部遍历一遍,所以我们可以将缩点中的点数作为边的权值(既然有权值那么我们就可以跑spfa),进行缩点之后就可以重新建图,所以在这里我们有三个first,nxt,v,然后我们要跑两边spfa,所以我们要有两个dis数组来保存正向和逆向的距离,然后只需要枚举每个点,同时用最大值来更新ans
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
const int maxn=100003;
stack<int> s;
queue<int> q;
int tot,tot1,tot2;
int v[maxn],v1[maxn],v2[maxn];
int nxt[maxn],nxt1[maxn],nxt2[maxn];
int first[maxn],f1[maxn],f2[maxn];
int ins[maxn],dfn[maxn],low[maxn];
int c[maxn],cnt[maxn],use[maxn];
int dis1[maxn],dis2[maxn];
int timing,col;
void add(int x,int y)
{v[tot]=y;nxt[tot]=first[x];first[x]=tot++;
}
void add1(int x,int y)
{v1[tot1]=y;nxt1[tot1]=f1[x];f1[x]=tot1++;
}
void add2(int x,int y)
{v2[tot2]=y;nxt2[tot2]=f2[x];f2[x]=tot2++;
}
void tarjan(int x)
{ins[x]=1;s.push(x);dfn[x]=low[x]=++timing;for(int to=first[x];to!=-1;to=nxt[to]){if(!dfn[v[to]]){tarjan(v[to]);low[x]=min(low[x],low[v[to]]);}else if(ins[v[to]])low[x]=min(low[x],low[v[to]]);}if(dfn[x]==low[x]){col++;int k;do{k=s.top();ins[k]=0;c[k]=col;cnt[col]++;s.pop();} while (k!=x);}
}
void spfa1(int x)
{dis1[x]=cnt[x];q.push(x);while(!q.empty()){int k=q.front();q.pop();for(int to=f1[k];to!=-1;to=nxt1[to]){if(dis1[v1[to]]<dis1[k]+cnt[v1[to]])dis1[v1[to]]=dis1[k]+cnt[v1[to]];if(!ins[v1[to]]){q.push(v1[to]);ins[v1[to]]=1;}}ins[k]=0;}
}
void spfa2(int x)
{dis2[x]=cnt[x];q.push(x);while(!q.empty()){int k=q.front();q.pop();for(int to=f2[k];to!=-1;to=nxt2[to]){if(dis2[v2[to]]<dis2[k]+cnt[v2[to]])dis2[v2[to]]=dis2[k]+cnt[v2[to]];if(!ins[v2[to]]){q.push(v2[to]);ins[v2[to]]=1;}}ins[k]=0;}
}
int main()
{int n,m,a,b,start;cin>>n>>m;memset(first,-1,sizeof(first));memset(f1,-1,sizeof(f1));memset(f2,-1,sizeof(f2));for(int k=0;k<m;k++){scanf("%d%d",&a,&b);add(a,b);}for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);start=c[1];for(int i=1;i<=n;i++)for(int to=first[i];to!=-1;to=nxt[to])if(c[i]!=c[v[to]]){add1(c[i],c[v[to]]);add2(c[v[to]],c[i]);}spfa1(start);spfa2(start);int ans=cnt[start];for(int i=1;i<=n;i++)if(!use[c[i]] && dis1[c[i]]){use[c[i]]=1;for(int to=f2[c[i]];to!=-1;to=nxt2[to]){if(!dis2[v2[to]])continue;ans=max(dis1[c[i]]+dis2[v2[to]]-cnt[start],ans);}}cout<<ans;return 0;
}
好像说了这么久,应该只有我自己一个人懂吧233333
另一个神犇的分层法暂时还没懂23333