[USACO15JAN]草鉴定Grass Cownoisseur

[USACO15JAN]草鉴定Grass Cownoisseur

缩点

题解:

缩点,变成DAG。
求每个点到1所在bcc的路径权值和f1,1所在的bcc到每个点的路径权值和f2。
枚举一条边(u->v),用f1[v]+f2[u]+1所在bcc的size更新答案。

Code:

#include 
#include 
#include 
#include 
#include 
#define D(x) cout<<#x<<" = "<
#define E cout<
using namespace std;
const int N = 100005;

int n,m,S;
int bcnt,tim,dfn[N],low[N]; stack<int> s;
int belong[N],bsz[N]; bool instack[N]; 
int f1[N],f2[N]; bool vis[N];

struct Edge{ int from,to,nxt,op; } e[N<<1], tp[N<<1];
int head[N], ec;
void add(int a,int b,int op=1){ 
    ec++; e[ec].from=a; e[ec].to=b; 
    e[ec].nxt=head[a]; head[a]=ec; e[ec].op=op;
}

void tarjan(int u){
    dfn[u]=low[u]=++tim;
    s.push(u); instack[u]=true;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(instack[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        bcnt++; int x=0;
        while(x!=u){
            x=s.top(); s.pop(); instack[x]=false;
            belong[x]=bcnt; bsz[bcnt]++;
        }
    }
}

void rebuild(){
    for(int i=1;i<=ec;i++) tp[i]=e[i];
    int tot=ec; ec=0; memset(head,0,sizeof(head));
    for(int i=1;i<=tot;i++){
        int u=tp[i].from, v=tp[i].to;
        u=belong[u]; v=belong[v];
        if(u!=v){ add(u,v,1); add(v,u,0); }
    }
}

void spfa(int op,int d[]){
    memset(vis,false,sizeof(vis));
    queue<int> q; q.push(S); d[S]=0;
    while(!q.empty()){
        int u=q.front(); q.pop(); vis[u]=false;
        for(int i=head[u];i;i=e[i].nxt){
            if(e[i].op!=op) continue;
            int v=e[i].to;
            if(d[v]if(!vis[v]){ vis[v]=true; q.push(v); }
            }
        }
    }
}

int main(){
    freopen("a.in","r",stdin);
    scanf("%d%d",&n,&m);
    int a,b;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        add(a,b);
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i]) tarjan(i);
    }
    S=belong[1];

//  D(bcnt); E;
//  for(int i=1;i<=n;i++) D(belong[i]); E;

    rebuild(); n=bcnt;
    for(int i=1;i<=n;i++) f1[i]=f2[i]=-N;
    spfa(1,f1); spfa(0,f2);
    int ans=bsz[S];
    for(int i=1;i<=ec;i++){
        int u=e[i].from, v=e[i].to;
        ans=max(ans,f1[v]+f2[u]+bsz[S]);
    }
    printf("%d\n",ans);
}

你可能感兴趣的:(缩点,<,图论,>,生成树)