题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3836
题解:将强连通子图缩成一个点(强连通图俩俩可达),使图成为无环图。要使图成为强连通图,每个点至少要有一个入度和一个出度,
一条边可以提供一个入度和一个出度,统计以上无环图没有入度顶点数和没有出度顶点数,从没有出度顶点连一条边到没有入度顶点,
边添加的数量为noIndegree和noOutdegree较大者。(hdu2767一样的题)
#include <stdio.h>
#include <string.h>
#define MAXN 20001
struct node
{
int to,next;
}edge[50001];
int n,m,belong[MAXN],indegree[MAXN],outdegree[MAXN];
int head[MAXN],instack[MAXN],low[MAXN],dfn[MAXN];
int stack[MAXN],tot,Dindex,top,Bcnt;
void Init()
{//初始化
tot=0,top=0,Dindex=0,Bcnt=0;
memset(head,-1,sizeof(head));
memset(instack,0,sizeof(instack));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(belong,0,sizeof(belong));
memset(indegree,0,sizeof(indegree));
memset(outdegree,0,sizeof(outdegree));
}
int Scan()
{
char ch;
int ret=0;
while((ch=getchar())<'0'||ch>'9');
while(ch>='0'&&ch<='9')
{
ret=ret*10+(ch-'0');
ch=getchar();
}
return ret;
}
void addEdge(int from,int to)
{
edge[tot].to=to;
edge[tot].next=head[from];
head[from]=tot++;
}
void Tarjan(int x)
{
int i,u,v;
dfn[x]=low[x]=++Dindex;//时间戳
stack[top++]=x;
instack[x]=1;
for(i=head[x];i!=-1;i=edge[i].next)
{
u=edge[i].to;
if(!dfn[u])
{
Tarjan(u);
low[x]=low[x]>low[u]?low[u]:low[x];
}
else if(instack[u]&&low[x]>dfn[u])
low[x]=dfn[u];
}
if(low[x]==dfn[x])
{
Bcnt++;
do
{
v=stack[--top];
instack[v]=0;
belong[v]=Bcnt;
} while (v!=x);
}
}
int getDegree()
{
int i,j,v,innum,outnum,ans;
for(i=1;i<=n;++i)
{
for(j=head[i];j!=-1;j=edge[j].next)
{
v=edge[j].to;
if(belong[i]!=belong[v])
{
outdegree[belong[i]]++;
indegree[belong[v]]++;
}
}
}
innum=outnum=0;
for(i=1;i<=Bcnt;++i)
{
if(indegree[i]==0)
innum++;
if(outdegree[i]==0)
outnum++;
}
ans=innum>outnum?innum:outnum;
return ans;
}
int main()
{
int x,y,i;
while(scanf("%d %d",&n,&m)!=EOF)
{
Init();
while(m--)
{
x=Scan();
y=Scan();
addEdge(y,x);//set X in a subset of set Y
}
for(i=1;i<=n;++i)
{
if(!dfn[i])
Tarjan(i);
}
if(Bcnt!=1)
{
x=getDegree();
printf("%d\n",x);
}
else
printf("0\n");
}
return 0;
}