[USACO15JAN]草鉴定Grass Cownoisseur
缩点
题解:
缩点,变成DAG。
求每个点到1所在bcc的路径权值和f1,1所在的bcc到每个点的路径权值和f2。
枚举一条边(u->v),用f1[v]+f2[u]+1所在bcc的size更新答案。
Code:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <stack>
#include <queue>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
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]<d[u]+bsz[v]){
d[v]=d[u]+bsz[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);
}