- -   - -   - -   - -
一个()打成[]  看了一晚上.....
/*
求强连通分量 kosaraju算法
边表存图 正反构造两个图
跑两边 分别记下入栈顺序 和每个强连通分量的具体信息 
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#define maxn 1010
#define maxx 10010
using namespace std;
int n,m,num,head1[maxn],head2[maxn],f[maxn],cnt;
int flag[maxn],ans[maxn][maxn];
stack<int>s;
struct node
{
    int u,v,per;
}e1[maxx],e2[maxx];
void Input()//输入 构图 e1为正 e2为反 
{
    int i,x,y;
    cin>>n>>m;
    for(i=1;i<=m;i++)
      {
          cin>>x>>y;
          num++;
          e1[num].u=x;
          e1[num].v=y;
          e1[num].per=head1[x];
          head1[x]=num;
          e2[num].u=y;
          e2[num].v=x;
          e2[num].per=head2[y];
          head2[y]=num;
      }
}
void Dfs1(int k)
{
    f[k]=1;
    for(int p=head1[k];p;p=e1[p].per)
      {
          if(!f[e1[p].v])
            Dfs1(e1[p].v);
      }
    s.push(k);//记录入栈顺序 
}
void Dfs2(int k)
{
    f[k]=1;
    ans[cnt][++ans[cnt][0]]=k;//记下第cnt个强连通分量的每个点 
    for(int i=head2[k];i;i=e2[i].per)
      if(f[e2[i].v]==0)
        Dfs2(e2[i].v);
    if(ans[cnt][0]>1)flag[k]=1;//如果第 cnt个强连通分量的大小>1 则x属于某个强连通分量 
}
void Kosaraju()
{
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++)//跑第一遍Dfs 每个点依次入栈 
      {
          if(f[i]==0)
            Dfs1(i);
      }
    memset(f,0,sizeof(f));
    while(!s.empty())//跑第二遍Dfs 标记每个点是否属于一个强连通分量 并计算数量 
      {
          int tmp=s.top();
          s.pop();
          if(f[tmp]==0)
            {
                cnt++;//计数强连通分量 
                Dfs2(tmp);
          }
      }
}
void Printf()
{
    for(int i=1;i<=n;i++)
      if(flag[i]==1)cout<<"T"<<endl;
      else cout<<"F"<<endl;
}
int main()
{
    Input();
    Kosaraju();
    Printf();
    return 0;
}