【USACO15JAN】芝生Cownoisseur G
タイトル説明
より良い彼の牛の放牧パターンを管理するための努力では、ファーマージョンは、すべて彼の農場の上に一方向の牛のパスがインストールされています。ファームは、好都合番号1 ... Nを、フィールドの対を接続する各一方向牛経路と、N個のフィールドから構成されています。フィールドXからYフィールドにパス接続する場合、例えば、その牛をXからYになくYからXへ旅行に許可されています
ベッシー牛は、我々はすべて知っているように、できるだけ多くのフィールドなどから草を食べて楽しんでいます。彼女はいつも一日の終わりにフィールド1に戻って、昼と訪問フィールドのシーケンスの最初にフィールド1で開始します。彼女が各1で草を食べるようになるので、彼女は(彼女が複数回フィールドを訪れた場合、彼女は一度だけそこに草を食べる)、彼女のルートに沿って個別のフィールドの数を最大化しようとします。
1想像の通り、これはおそらく、彼女はおそらく彼女の日常のルートに沿って訪問することができます明確なフィールドの数を減らすことになるので、ベッシーは、FJのパス上の一方通行の制限については特に満足していないです。彼女は、ルールを破ると、間違った方向に1つのパスに追従している場合、彼女が食べることができるようになりますどのくらいの草不思議。彼女は彼女が間違った方向にルートに沿って一つのパスにフォローアップすることができ、ルートから始まり、フィールド1で終わる、一緒に訪問することができます個別のフィールドの最大数を計算してください。彼女の旅に一度ベッシーはせいぜい後方に移動することができます。特に、彼女も後方二度同じパスを取ることはできません。
ジョンが有するn個のブロックが草地、牧草地通行複数の接続されたnまで番号1、。ベッシーは、牛の牧草地は、彼女が味に多くの牧草として到達したかった、おいしい目利きです。
ベッシーは常に1番から始まる牧草地、そして最終的に戻って第1牧場へ。彼女は多くの牧草地として通過したかった、ベッシーは、牧草地で草を通じて一度何度牧草を食べます。牧草地は、ベッシーは大きな不便をもたらしたテイスティング仕事を与える一方向接続であるため、ベッシーは密かに散歩を逆にしたいのですが、一つだけ逆行を持つことができます。彼は草の牧草を食べにベッシー数アップを尋ねました。
入力形式
INPUT:(ファイルgrass.in)
入力の最初の行は、フィールドの数および一方向パスの数(1 <= N、M <= 100,000)を得、NおよびMを含有します。
次のM行はそれぞれ一方向牛のパスを記述する。各行には、同じ牛のパスが複数回表示されることはありませんXからYに牛のパスに対応し、二つの異なるフィールド番号XとYが含まれています。
入力:
最初のライン:牧草数N、道路の数m。
m行、各行は、x、xとy yの一方向エッジがパスを重複しない示します。
出力フォーマット
OUTPUT:(ファイルgrass.out)
異なるフィールドの最大数を示す単一ラインベッシー
彼女ができることを考えると、フィールド1から開始と終了の経路に沿って訪問することができます
間違った方向にこのルートに沿って最大で1つのパスに従ってください。
出力:
数は、逆行性には、いくつかの牧草地まで行くことができます。
DAG、及びトポロジに凝縮点Tarjan後見つけるためにI(1 <= I <= n)の最大値の、DIS1 [I]と呼ばれる、Iおよび内蔵逆側、トポロジー要求1(1 < = I <= n)の最大値の、DIS2と呼ぶ[i]は、これは1、iの最大値を求めると等価です。
次に、各エッジを列挙し、例えばU-> Vので、U-> Vが逆ならば、ANS = MAX(DIS2 [U] + DIS1 [V] -w [FA [1])。
ここでは需要ANSピットは、あることを確認dis1,2にある[i]はすべきではない0、1を達することができること、それ以外の場合は計算できません。
難易度:予想外の困難は、各エッジ方向を列挙するために許可されています。
コード:
#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=200100;
const int M=1000100;
const LL mod=100000000;
int dfn[N],low[N],sta[N],tot,head[N],cnt,ans,top,L[N],R[N],fa[N],w[N];
int dis1[N],dis2[N],in[N];
int n,m;
bool vis[N];
struct Node{
int to,nex;
}edge[M];
void add(int p,int q){
edge[cnt].to=q;
edge[cnt].nex=head[p];
head[p]=cnt++;
}
void Tarjan(int p){
dfn[p]=++tot,low[p]=tot;
if(!vis[p]) vis[p]=true,sta[++top]=p;
for(int i=head[p];~i;i=edge[i].nex){
int q=edge[i].to;
if(!dfn[q]){
Tarjan(q);
low[p]=min(low[p],low[q]);
}
else if(vis[q]) low[p]=min(low[p],dfn[q]);
}
if(dfn[p]==low[p]){
vis[p]=false,fa[p]=p,w[p]=1;
while(sta[top]!=p){
fa[sta[top]]=p;
vis[sta[top]]=false;
w[p]++;
top--;
}
top--;
}
}
void bfs(int p,int q){
queue<int>qu;
for(int i=1;i<=n;i++){
if(fa[i]==i&&in[i]==0) qu.push(i);
}
if(q==1) dis1[p]=w[p];
else if(q==2) dis2[p]=w[p];
while(!qu.empty()){
int u=qu.front();
qu.pop();
for(int i=head[u];~i;i=edge[i].nex){
int v=edge[i].to;
if(q==1&&dis1[u]) dis1[v]=max(dis1[u]+w[v],dis1[v]);
else if(q==2&&dis2[u]) dis2[v]=max(dis2[u]+w[v],dis2[v]);
in[v]--;
if(in[v]==0) qu.push(v);
}
}
}
int main(){
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&L[i],&R[i]);
add(L[i],R[i]);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) Tarjan(i);
}
cnt=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++){//缩点
if(fa[L[i]]!=fa[R[i]]){
in[fa[R[i]]]++;//入度
add(fa[L[i]],fa[R[i]]);
}
}
bfs(fa[1],1);//1-i的最长路径
cnt=0;
memset(in,0,sizeof(in));
memset(head,-1,sizeof(head));//重新反向建边
for(int i=1;i<=m;i++){//缩点
if(fa[L[i]]!=fa[R[i]]){
in[fa[L[i]]]++;//入度
add(fa[R[i]],fa[L[i]]);
}
}
bfs(fa[1],2);//i-1的最长路径
ans=w[fa[1]];
for(int i=1;i<=m;i++){
if(fa[L[i]]!=fa[R[i]]){
int u=fa[L[i]],v=fa[R[i]];
if(dis1[v]&&dis2[u]) ans=max(ans,dis2[u]+dis1[v]-w[fa[1]]);
}
}
cout<<ans<<endl;
return 0;
}