洛谷原题
好题啊。这道题非常好。
我的思路是首先把原图的强连通分量缩点(这是人都能想到),然后就卡壳了。
非常无耻地看了看题解。
因为原题可以逆向,所以我们需要建两个图,这两个图之间的边是逆向的(也就是逆向走的桥梁)。然后跑SPFA最长路即可。
注意数组大小。
代码写的很好看。
#include
#include
#include
#include
#define LL long long
#define mem(s,v) memset(s,v,sizeof(s))
#define FILEIN(s) freopen(s".in","r",stdin)
#define FILEOUT(s) freopen(s".out","w",stdout)
#define FILE(s) FILEIN(s);FILEOUT(s)
using namespace std;
template<class Type>
inline Type read(Type &num){
Type x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
const int maxn=200005;
int n,m,head[maxn<<1],tot;
int dfn[maxn],low[maxn],num,cnt,stack[maxn],top,bl[maxn],siz[maxn<<1];
bool ins[maxn];
int head_new[maxn<<1],tot_new;
int dis[maxn<<1];
bool vis[maxn<<1];
struct Edge{
int y,next;
Edge(){}
Edge(int _y,int _n):y(_y),next(_n){}
}e[maxn<<2],e_new[maxn<<2];
queue<int>q;
inline void connect(int x,int y){
e[++tot]=Edge(y,head[x]);
head[x]=tot;
}
inline void connect_new(int x,int y){
e_new[++tot_new]=Edge(y,head_new[x]);
head_new[x]=tot_new;
}
void Tarjan(int x){
dfn[x]=low[x]=++num;
stack[++top]=x;ins[x]=true;
for(register int i=head[x];i;i=e[i].next){
int y=e[i].y;
if(!dfn[y]){
Tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(ins[y]){
low[x]=min(low[x],dfn[y]);
}
}
if(dfn[x]==low[x]){
int y;++cnt;
do{
y=stack[top--];ins[y]=false;
bl[y]=cnt;siz[cnt]++;
}while(x!=y);
}
}
inline void spfa(){
q.push(bl[1]);
vis[bl[1]]=true;
while(q.size()){
int x=q.front();q.pop();vis[x]=false;
for(register int i=head_new[x];i;i=e_new[i].next){
int y=e_new[i].y;
if(dis[y]<dis[x]+siz[x]){
dis[y]=dis[x]+siz[x];
if(!vis[y]){
q.push(y);vis[y]=true;
}
}
}
}
printf("%d\n",dis[bl[1]+cnt]);
}
int main(){
n=read(n);m=read(m);
for(register int i=1;i<=m;++i){
int x=read(x),y=read(y);
connect(x,y);
}
for(register int i=1;i<=n;++i){
if(!dfn[i])Tarjan(i);
}
for(register int i=1;i<=cnt;++i)siz[i+cnt]=siz[i];
for(register int x=1;x<=n;++x){
for(register int i=head[x];i;i=e[i].next){
int y=e[i].y;
if(bl[y]!=bl[x])
connect_new(bl[x],bl[y]),
connect_new(bl[y],bl[x]+cnt),//逆向走的桥梁(两个图之间的桥梁)
connect_new(bl[x]+cnt,bl[y]+cnt);
}
}
connect_new(bl[1],bl[1]+cnt);
spfa();
return 0;
}
贴一张美美的图。完结撒花。