1742. Team building

http://acm.timus.ru/problem.aspx?space=1&num=1742

连通分量 

方法: 找到环 缩点  建立新图 新图是一个森林

新建的的森林 有多少节点 那么就有最多多少team   有多少叶子节点 那么最少就有多少team

注意由于n比较太 如果原图有一条很长的直线的话 会爆栈  所以自己开了一个栈  这种错误多次遇到 以后要注意呀

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<vector>

#include<map>

#include<cmath>

#include<queue>

#include<stack>

#include<algorithm>



#define LL long long

#pragma comment(linker, "/STACK:1024000000,1024000000")



using namespace std;

const int INF=0x3f3f3f3f;

const int N=100005;

vector<int>str[N];

vector<int>newtree[N];

int dfn[N],low[N],f[N],deep;

bool in[N],visited[N];

int minnum,maxnum;

int st[N],I;

void buildtree(int x)

{//cout<<x<<endl;

    for(unsigned int i=0;i<str[x].size();++i)

    {

        if(f[x]!=f[str[x][i]])

        {newtree[f[x]].push_back(f[str[x][i]]);}

    }

}

void Tarjan(int x)

{

    low[x]=dfn[x]=deep++;

    in[x]=true;

    visited[x]=true;

    st[I++]=x;

    for(unsigned int i=0;i<str[x].size();++i)

    {

        if(!visited[str[x][i]])

        {

            Tarjan(str[x][i]);

            low[x]=min(low[x],low[str[x][i]]);

        }else if(in[str[x][i]]==true)

        {

            low[x]=min(low[x],dfn[str[x][i]]);

        }

    }

    if(dfn[x]==low[x])

    {

        int k=I;

        while(st[k-1]!=x)

        {

            f[st[k-1]]=x;

            in[st[k-1]]=false;

            --k;

        }

        f[x]=x;

        in[x]=false;

        while(st[--I]!=x)

        buildtree(st[I]);

        buildtree(st[I]);

    }

}

void dfs(int x)

{

    ++maxnum;

    visited[x]=true;

    if(newtree[x].size()==0)

    {++minnum;return ;}

    for(unsigned int i=0;i<newtree[x].size();++i)

    {

        if(!visited[newtree[x][i]])

        dfs(newtree[x][i]);

    }

}

int main()

{

    //freopen("data.txt","r",stdin);

    int n;

    while(cin>>n)

    {

       for(int i=1;i<=n;++i)

       {str[i].clear();newtree[i].clear();}

       for(int i=1;i<=n;++i)

       {

           int pre;

           cin>>pre;

           str[pre].push_back(i);

           //cout<<f<<" "<<i<<endl;

       }

       memset(visited,false,sizeof(visited));

       deep=0;

       I=0;

       for(int i=1;i<=n;++i)

       if(visited[i]==false)

       Tarjan(i);

       minnum=0;

       maxnum=0;

       memset(visited,false,sizeof(visited));

       for(int i=1;i<=n;++i)

       {

           if(!visited[i]&&f[i]==i)

           dfs(i);

       }

       cout<<minnum<<" "<<maxnum<<endl;

    }

    return 0;

}

 

你可能感兴趣的:(Build)