[USACO15JAN]草鉴定Grass Cownoisseur
缩点后从正向和反向搜一遍得到两批点,1能到达的点和能到1的点,处理出到达这些点最多可以经过的点数,再枚举能连上边的点求一求就好了
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
const int N=100010;
int n, m, idx, dfn[N], low[N], vis[N], x[N], y[N], typ1[N], typ2[N], w1[N], w2[N];
int col[N], tot, cnt[N], sta[N], top, f[N];
int head[N], now;
struct E {int to, next;} e[N<<4];
void add(int u, int v){e[++now]=(E){v, head[u]}; head[u]=now;}
void tarjan(int u)
{
dfn[u]=low[u]=++idx; vis[u]=1; sta[++top]=u; int v;
for(int i=head[u]; i; i=e[i].next){if(!dfn[v=e[i].to]) {tarjan(v); low[u]=min(low[v], low[u]);} else if(vis[v]) low[u]=min(low[u], dfn[v]);}
if(low[u] == dfn[u]) {++tot; while(sta[top+1] != u) {int x=sta[top--]; col[x]=tot; vis[x]=0; cnt[tot]++;}}
}
void dfs1(int u){typ1[u]=1; for(int i=head[u]; i; i=e[i].next) {int v=e[i].to; if(!typ1[v]) dfs1(v);}}
void dfs2(int u){typ2[u]=1; for(int i=head[u]; i; i=e[i].next) {int v=e[i].to; if(!typ2[v]) dfs2(v);}}
void spfa1()
{
memset(vis, 0, sizeof(vis));
w1[col[1]]=cnt[col[1]]; vis[col[1]]=1;
queue<int>q; q.push(col[1]);
while(!q.empty())
{
int u=q.front(); q.pop(); vis[u]=0;
for(int i=head[u]; i; i=e[i].next)
{
int v=e[i].to;
if(w1[v] < w1[u]+cnt[v]) {w1[v]=w1[u]+cnt[v]; if(!vis[v]) q.push(v); vis[v]=1;}
}
}
}
void spfa2()
{
memset(vis, 0, sizeof(vis));
w2[col[1]]=cnt[col[1]]; vis[col[1]]=1;
queue<int>q; q.push(col[1]);
while(!q.empty())
{
int u=q.front(); q.pop(); vis[u]=0;
for(int i=head[u]; i; i=e[i].next)
{
int v=e[i].to;
if(w2[v] < w2[u]+cnt[v]) {w2[v]=w2[u]+cnt[v]; if(!vis[v]) q.push(v); vis[v]=1;}
}
}
}
int read(){
int out=0, f=1; char c=getchar(); while(c < '0' || c > '9') {if(c == '-') f=-1; c=getchar();}
while(c >= '0' && c <= '9') {out=(out<<1)+(out<<3)+c-'0'; c=getchar();}
return out*f;
}
void solve()
{
n=read(), m=read();
for(int i=1; i <= m; i++) x[i]=read(), y[i]=read(), add(x[i], y[i]);
for(int i=1; i <= n; i++) if(!dfn[i]) tarjan(i);
memset(head, 0, sizeof(head)); memset(e, 0, sizeof(e)); now=0;
for(int i=1; i <= m; i++) if(col[x[i]] != col[y[i]]) add(col[x[i]], col[y[i]]); dfs1(col[1]); spfa1();
memset(head, 0, sizeof(head)); memset(e, 0, sizeof(e)); now=0;
for(int i=1; i <= m; i++) if(col[x[i]] != col[y[i]]) add(col[y[i]], col[x[i]]); dfs2(col[1]); spfa2();
int ans=0;
for(int i=1; i <= tot; i++) if(typ1[i])
for(int j=head[i]; j; j=e[j].next) {int v=e[j].to; if(typ2[v]) ans=max(ans, w1[i]+w2[v]-cnt[col[1]]);}
printf("%d", ans);
}
int main()
{
//freopen("testdata.in","r",stdin);
solve();
return 0;
}