//未完成
#include<iostream>
#include<stack>
using namespace std;
#define MaxNum 5005
struct Node{
int dest;
struct Node *next;
}*node[MaxNum],*nMap[MaxNum],*p;
stack<int>Q;
bool Visited[MaxNum],InStack[MaxNum],nMapMax[MaxNum];
int dfn[MaxNum],low[MaxNum],belong[MaxNum];
int nMapNum[MaxNum],nMapNumOld[MaxNum],nMapInNum[MaxNum];
int nTime,beNum,N,M,testNO;
int nTopoSub;
void AddNode(int st,int end,struct Node *tnode[]){
p=new struct Node;
p->dest=end;
p->next=tnode[st];
tnode[st]=p;
}
void Init(){//初始化
scanf("%d%d",&N,&M);
memset(Visited,false,sizeof(Visited));
memset(InStack,false,sizeof(InStack));
memset(nMapInNum,0,sizeof(nMapInNum));//新图入度,拓扑排序用
memset(nMapMax,false,sizeof(nMapMax));//输出用,判断是否是要输出的连通子集
memset(nMapNum,0,sizeof(nMapNum));
while(!Q.empty())
Q.pop();
nTime=beNum=testNO=0;
int i;
for(i=0;i<N;i++)//清空图
nMap[i]=node[i]=NULL;
int a,b;
for(i=0;i<M;i++){//建立原图
scanf("%d%d",&a,&b);
AddNode(a,b,node);
}
}
int min(int ta,int tb){
if(ta>tb) return tb;
return ta;
}
void Tarjan(int t){
low[t]=dfn[t]=++nTime;
Q.push(t);
Visited[t]=InStack[t]=true;
struct Node *q;
int x;
for(q=node[t];q!=NULL;q=q->next){
x=q->dest;
if(!Visited[x]){
Tarjan(x);
low[t]=min(low[t],low[x]);
}
else if(InStack[x])
low[t]=dfn[x];
}
if(dfn[t]==low[t]){//找到一个连通子集
do{
x=Q.top();
belong[x]=beNum;
InStack[x]=false;
Q.pop();
nMapNum[beNum]++;//记录各个连通子集的顶点数
}while(x!=t);
beNum++;
}
}
void Doit(){
int i;
for(i=0;i<N;i++){
if(!Visited[i])
Tarjan(i);
}
int x;
struct Node *q;
for(i=0;i<N;i++){//建立新图
for(q=node[i];q!=NULL;q=q->next){
x=q->dest;
if(belong[i]!=belong[x]){
AddNode(belong[i],belong[x],nMap);
nMapInNum[belong[x]]++;
}
}
}
memset(Visited,false,sizeof(Visited));//用于标记是否已经拓扑排序过
for(i=0;i<beNum;i++)
nMapNumOld[i]=nMapNum[i];//保留记录子连通图的个数
int y=beNum;
while(y--){
for(i=0;i<beNum;i++){//找到新图中入度为0的点
if(!Visited[i] && nMapInNum[i]==0){
nTopoSub=i;
Visited[i]=true;
break;
}
}
for(q=nMap[i];q!=NULL;q=q->next){
x=q->dest;
nMapInNum[x]--;//入度减1
nMapNum[x]+=nMapNum[i];//因为具有传递性,拥有的顶点加上支持该点的所有顶点
}
}
//输出
int sub,max=-1,h=0;
for(i=0;i<beNum;i++){//计算拥护者最多的
if(nMapNum[i]>max){
sub=i;
max=nMapNum[i];
}
}
for(i=0;i<beNum;i++){
if(nMapNum[i]==max){
h+=nMapNumOld[i];//加上该连通子集本身的顶点数
nMapMax[i]=true;
}
}
printf("Case %d: %d\n",++testNO,nMapNum[sub]-1);
for(i=0;i<N && h>1;i++){//将拥护者最多的那个强连通子集全部输出
if(nMapMax[belong[i]]){
printf("%d ",i);
h--;
}
}
while(h==1){
if(nMapMax[belong[i]]){
printf("%d\n",i);
h--;
}
i++;
}
}
int main()
{
int K;
scanf("%d",&K);
while(K--){
Init();
Doit();
}
return 0;
}
【个人专题一】强连通——Hoj_3639(RE)
最新推荐文章于 2017-08-16 15:14:28 发布