[USACO15JAN]草鉴定Grass Cownoisseur 【Tarjan+搜索】

[USACO15JAN]草鉴定Grass Cownoisseur

缩点后从正向和反向搜一遍得到两批点,1能到达的点和能到1的点,处理出到达这些点最多可以经过的点数,再枚举能连上边的点求一求就好了

代码

#include
#include
#include
#include
#include
#include
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;
}

你可能感兴趣的:(图论)