题目:http://acm.hdu.edu.cn/showproblem.php?pid=2767
题意:给出一个有向图,要求添加最少的边数使得该有向图变成强连通的。
分析:Tarjan模板题,加缩点。注意,如果全部缩成一个点的话,要特别判断。
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2767
题意:给出一个有向图,要求添加最少的边数使得该有向图变成强连通的。
分析:Tarjan模板题,加缩点。注意,如果全部缩成一个点的话,要特别判断。
#define pb push_back
const int maxn(5+20000);
vector<int>adj[maxn];
int n,m;
int indd,dfn[maxn],low[maxn];
int sta[maxn],numsta;
int id[maxn],numid;
bool insta[maxn];
void dfsAA(int a)
{
dfn[a] = low[a] = ++indd;
sta[++numsta] = a;
insta[a] = true;
int s,f,b;
for(s=adj[a].size(),f=0; f < s; f++)
{
b = adj[a].at(f);
if(!dfn[b])
{
dfsAA(b);
low[a] = min(low[a], low[b]);
}
else if(insta[b])
low[a] = min(low[a], dfn[b]);
}
if(dfn[a] == low[a])
{
numid++;
do
{
b = sta[numsta--];
insta[b] = false;
id[b] = numid;
}while(b != a);
}
}
void Tarjan()
{
indd = numsta = numid = 0;
memset(dfn, 0, sizeof dfn);
memset(insta, false, sizeof insta);
for(int e=1; e <= n; e++)
if(!dfn[e])
dfsAA(e);
}
int inde[maxn],outde[maxn];
int cyh()
{
Tarjan();
if(numid == 1)
return 0;
memset(inde, 0, sizeof inde);
memset(outde, 0, sizeof outde);
int e,f,s,b,suma=0,sumb=0;
for(e=1; e <= n; e++)
{
for(s=adj[e].size(),f=0; f < s; f++)
{
b = adj[e].at(f);
if(id[e] != id[b])
{
inde[id[b]]++;
outde[id[e]]++;
}
}
}
for(e=1; e <= numid; e++)
{
suma += (inde[e]==0);
sumb += (outde[e]==0);
}
return max(suma, sumb);
}
int main()
{
int test,e,st,en;
for(cin>>test; test--; )
{
cin>>n>>m;
for(e=1; e <= n; e++)
adj[e].clear();
while(m--)
{
scanf("%d %d", &st,&en);
adj[st].pb(en);
}
printf("%d\n", cyh() );
}
return 0;
}