ロサンゼルス最大の食物連鎖数バレーP4017
トピックの背景
あなたは食物連鎖にそれを知っていますか?デリア生物学的試験、彼女は常に少数または数が不足して、いくつかを繰り返しているため、食物連鎖すべて間違っをカウントの対象。そこで彼女が来て助け、あなたを、あなたはああではないでしょう!彼女を助けるためにプログラムを書きます。
タイトル説明
あなたの食物網を与え、あなたは食物網における最大の食物連鎖の数を尋ねました。
(を参照ここで、「最大の食物連鎖」、生物学的な意味での食物連鎖で、一番左の生産者は右、他の生物による捕食があり、ほとんどの消費者はならないことを他の種を捕食ではありません。)
デリアは非常に急務となっているので、あなただけの1秒を持っています。
この結果は大きすぎる可能性がありますので、あなただけの80112002金型の総出力を必要とします。
入力形式
最初の行、2つの正の整数N、M、及びN食べ食品関係の数mの種を表します。
2つの正の整数の次のm行は、Aは、食べと生物Bを食べ表します
出力フォーマット
整数、食物連鎖の結果、80112002型の最大数に並びます。
サンプル入力と出力
入力#1コピー
出力#1コピー
説明/ヒント
各テストポイントは、次の規則を満たします:
[補足]
中央データは、要件の生物学を満たすためには表示されません。(おかげで@AKEE)
ソリューション:
良い質問トポロジカル整列。
予備知識はトポロジカル整列です。小さなパートナー会場ではない場合:
私は個人的に自分自身をソートすることトポロジカルを理解することは特に困難ではありませんが、アプリケーションが対象にそう簡単ではなかったと思います。
まず、この質問は、図のトピックであることがわかります。(これは本当にGGを見ることができない場合)
図のトピックについては、我々はテンプレートとアルゴリズムを判断するために、有効にする対象を分析します。この質問は、その後でそれをソートするトポロジカルなぜ使用?
まず第一に、我々は最大の食物連鎖、最大の食物連鎖を探している、それは何ですか?対象の説明によると、生き物の最も激しいの種類は、任意の生物学的に食わすることができないで、最も弱いクリーチャーはどんな生き物を食べることができません。度に図の類似点0から点0度です。私達はちょうどこの金額のすべてをすることができ見つける必要があります。
あなたは再帰的な数の問題を解決することができます。
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=5010;
const int maxm=5*1e5+10;
const int mod=80112002;
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
int x=0,f=1;
char ch=nc();
while(ch<48){if(ch=='-')f=-1;ch=nc();}
while(ch>47) x=(((x<<2)+x)<<1)+ch-48,ch=nc();
return x*f;
}
int n,m;
int tot,head[maxn],nxt[maxm],to[maxm];
int chudu[maxn],rudu[maxn];
int f[maxn],ans;
queue<int> q;
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
int main()
{
n=read();m=read();
for(int i=1;i<=m;i++)
{
int a=read();
int b=read();
add(a,b);
rudu[b]++;
chudu[a]++;
}
for(int i=1;i<=n;i++)
if(rudu[i]==0)
f[i]=1,q.push(i);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
f[y]=(f[y]+f[x])%mod;
rudu[y]--;
if(rudu[y]==0)
{
q.push(y);
if(chudu[y]==0)
ans=(ans+f[y])%mod;
}
}
}
printf("%d",ans);
return 0;
}