题意是加多少条边能使图成为强连通。。。。
将一个强连通分量缩成一个点,构成一个DAG,添加至少max(入度为0的个数,出度为0的个数)条边即可,原因不好解释。。DAG每个入度不为0的点可以由某个入度为0的点出发到达(yy一下就能明白),把出度为0的点连向入度为0的点即可。。max(入度为0的个数,出度为0的个数)
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct node
{
int u,v;
};
node e[100000];
int first[55555],next[100000];
int cc,flag[55555],dfn[55555],low[55555];
int sum,top,stack[55555];
int in[55555],out[55555],time;
inline void add_edge(int u,int v)
{
e[cc].u=u;
e[cc].v=v;
next[cc]=first[u];
first[u]=cc;
cc++;
}
int tardfs(int s)
{
flag[s]=1;
low[s]=dfn[s]=time++;
stack[++top]=s;
int i;
for(i=first[s];i!=-1;i=next[i])
{
if(flag[e[i].v]==0)
tardfs(e[i].v);
if(flag[e[i].v]==1)
low[s]=min(low[e[i].v],low[s]);
}
if(dfn[s]==low[s])
{
++sum;
do
{
low[stack[top]]=sum;
flag[stack[top]]=2;
}while(stack[top--]!=s);
}
return 0;
}
int tarjan(int n)
{
sum=0;
time=1;
memset(flag,0,sizeof(flag));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
int i;
top=0;
for(i=1;i<=n;i++)
{
if(flag[i]==0)
tardfs(i);
}
if(sum==1)
return 0;
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for(i=1;i<=n;i++)
{
int j;
for(j=first[i];j!=-1;j=next[j])
{
if(low[e[j].v]!=low[e[j].u])
{
out[low[e[j].u]]++;
in[low[e[j].v]]++;
}
}
}
int res1=0,res2=0;
for(i=1;i<=sum;i++)
{
if(in[i]==0)
res1++;
if(out[i]==0)
res2++;
}
return max(res1,res2);
}
int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{
int n,m;
scanf("%d%d",&n,&m);
memset(first,-1,sizeof(first));
memset(next,-1,sizeof(next));
int i;
cc=0;
for(i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
}
int ans=tarjan(n);
printf("%d\n",ans);
}
return 0;
}