/********************************************************************
** @file poj1236.cpp
** @date Wed Apr 27 19:59:56 2011
** @brief *******强连通分支+缩点**********
**
********************************************************************/
#include<iostream>
#include<cstring>
#include<stack>
#include<vector>
using namespace std;
#define MAX 103
vector<int>v[MAX];
int n,length=0;
stack<int>s;
int DFN[MAX];//定义DFN(u)为节点u搜索的次序编号(时间戳),
int low[MAX];/*Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号 */
bool inStack[MAX];
int belong[MAX];/*belong[i]表示第i个节点输入belong[i]分支 */
int number=0;
bool in[MAX];//标记一个连通分支的入度是否为0
bool out[MAX];//标记一个连通分支出度是否为0
void init(){
cin>>n;int j,num;
for(int i=0;i<n;++i){
while(cin>>num){
if(num==0)break;
v[i].push_back(num-1);//第i个顶点与num-1这个顶点相连
}
}
}
void Tarjan(int u){//u是从0开始,也就是顶点是0,1,2,3,.......
DFN[u]=low[u]=length++;
inStack[u]=true;
s.push(u);int j;
for(int i=0;i<v[u].size();++i){
j=v[u][i];//找到与顶点u相连的j
if(DFN[j]==-1){
Tarjan(j);
low[u]=min(low[u],low[j]);
}
else if (inStack[j]){
low[u]=min(low[u],DFN[j]);
}
}
if(low[u]==DFN[u]){
number++;//分支个数
do{
j=s.top();s.pop();
belong[j]=number;//标记各个点属于哪个分支1,2,3,.........
inStack[j]=false;
}while(j!=u);
}
}
void solve(){
memset(DFN,-1,sizeof(DFN));
memset(low,-1,sizeof(low));
memset(inStack,0,sizeof(inStack));
for(int i=0;i<n;++i)
if(DFN[i]==-1)
Tarjan(i);
}
int main(int argc, char *argv[])
{
init();
solve();
memset(out,true,sizeof(out));
memset(in,true,sizeof(in));
for(int i=0;i<n;++i){
for(int j=0;j<v[i].size();++j){
int d=v[i][j];
int u=belong[i];int vv=belong[d];
if(u!=vv) {//次两点属于两个不同的连通分支,相应的入度,出度不为0
out[u]=false;//标记相应的出度不为0
in[vv]=false;
}
}
}
int num_in=0,num_out=0;
for(int i=1;i<=number;++i){
if(out[i]==true)num_out++;
if(in[i]==true)num_in++;
}
cout<<num_in<<endl<<(number==1?0:max(num_in,num_out))<<endl;
return 0;
}
poj1236 强连通分支+缩点
最新推荐文章于 2017-07-14 15:21:00 发布