poj 2553 (tarjan求强连通分量+缩点)

来源:互联网 发布:网络计算机组成 编辑:程序博客网 时间:2024/05/21 12:05

        题目大意:  给定一个n个点的有向图( 1<=n<=5000 ),要求你输出所有满足条件的点,条件是点在 出度为0的强连通分量里,点要按标号大小升序输出。tarjan太强大了,,Source CodeProblem: 2553User: 1013101127Memory: 808KTime: 266MSLanguage: C++Result: AcceptedSource Code#include<iostream>#include<cstdio>#include <cmath>#include <vector>#include <stack>;#include<cstring>using namespace std;const int nMax=5005;const int mMax=9000005;int n,m;vector<int >mp[nMax];stack<int>mystack;int dfn[nMax];int low[nMax];int vis[nMax];int tmp;int belong[nMax];int cnt;int out[nMax];void tarjan(int u){   dfn[u]=low[u]=tmp;   tmp++;   vis[u]=1;   mystack.push(u);   for(int i=0;i<mp[u].size();i++)   {       int v=mp[u][i];       if(!dfn[v])       {         tarjan(v);         low[u]=min(low[u],low[v]);       }       else if(vis[v])       {         low[u]=min(dfn[v],low[u]);       }   }   if(low[u]==dfn[u])   {      ++cnt;      int v;      do      {          v=mystack.top();          mystack.pop();          vis[v]=0;          belong[v]=cnt;      }while(v!=u);   }} void dfs(int u) {     vis[u]=1;     for(int i=0;i<mp[u].size();++i)     {         int v= mp[u][i];         if( belong[u] != belong[v] )             out[ belong[u] ]++;         if( !vis[v] )             dfs( v );     } }int main(){ while(cin>>n){    if(!n)break;    cin>>m;    int u,v;    tmp=1;    cnt=0;    memset(vis,0,sizeof(vis));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(out,0,sizeof(out));    for(int i=1;i<=n;i++)    mp[i].clear();    while(!mystack.empty())    mystack.pop();    for(int i=0;i<m;i++)    {        cin>>u>>v;        mp[u].push_back(v);    }    for(int i=1;i<=n;i++)    {        if(!dfn[i])        tarjan(i);    }        memset(vis,0,sizeof(vis));        memset(out,0,sizeof(out));         for(int i=1;i<=n;++i)         {             if( !vis[i] )                 dfs(i);         }    vector<int>ans;    ans.clear();         for(int i=1;i<=n;++i)             if( out[ belong[i] ] == 0 )                 ans.push_back( i );         for(int i=0;i<ans.size();++i)            printf("%d%c", ans[i], i==ans.size()-1 ? '\n' : ' ' );    }    return 0;}

        题目大意:

  给定一个n个点的有向图( 1<=n<=5000 ),要求你输出所有满足条件的点,条件是点在 出度为0的强连通分量里,点要按标号大小升序输出。

tarjan太强大了,,

Source Code

Problem: 2553 User: 1013101127Memory: 808K Time: 266MSLanguage: C++ Result: Accepted
  • Source Code
    #include<iostream>#include<cstdio>#include <cmath>#include <vector>#include <stack>;#include<cstring>using namespace std;const int nMax=5005;const int mMax=9000005;int n,m;vector<int >mp[nMax];stack<int>mystack;int dfn[nMax];int low[nMax];int vis[nMax];int tmp;int belong[nMax];int cnt;int out[nMax];void tarjan(int u){   dfn[u]=low[u]=tmp;   tmp++;   vis[u]=1;   mystack.push(u);   for(int i=0;i<mp[u].size();i++)   {       int v=mp[u][i];       if(!dfn[v])       {         tarjan(v);         low[u]=min(low[u],low[v]);       }       else if(vis[v])       {         low[u]=min(dfn[v],low[u]);       }   }   if(low[u]==dfn[u])   {      ++cnt;      int v;      do      {          v=mystack.top();          mystack.pop();          vis[v]=0;          belong[v]=cnt;      }while(v!=u);   }} void dfs(int u) {     vis[u]=1;     for(int i=0;i<mp[u].size();++i)     {         int v= mp[u][i];         if( belong[u] != belong[v] )             out[ belong[u] ]++;         if( !vis[v] )             dfs( v );     } }int main(){ while(cin>>n){    if(!n)break;    cin>>m;    int u,v;    tmp=1;    cnt=0;    memset(vis,0,sizeof(vis));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(out,0,sizeof(out));    for(int i=1;i<=n;i++)    mp[i].clear();    while(!mystack.empty())    mystack.pop();    for(int i=0;i<m;i++)    {        cin>>u>>v;        mp[u].push_back(v);    }    for(int i=1;i<=n;i++)    {        if(!dfn[i])        tarjan(i);    }        memset(vis,0,sizeof(vis));        memset(out,0,sizeof(out));         for(int i=1;i<=n;++i)         {             if( !vis[i] )                 dfs(i);         }    vector<int>ans;    ans.clear();         for(int i=1;i<=n;++i)             if( out[ belong[i] ] == 0 )                 ans.push_back( i );         for(int i=0;i<ans.size();++i)            printf("%d%c", ans[i], i==ans.size()-1 ? '\n' : ' ' );    }    return 0;}

原创粉丝点击