给出一个有向图,问至少加上多少条边,可以使该图变成一个强联通图
用tarjan算法缩点后,在所有点里面的出度和入度里面取最大。
F #include <iostream>
#include <cmath>
#include<stdlib.h>
#include<vector>
#include<cstring>
using namespace std;
#define N 33333
#define M 111111
int n, m;
struct Edge{
int from, to, nex;
bool sign;
}edge[M<<1];
int head[N], edgenum;
void add(int u, int v){
Edge E={u, v, head[u], false};
edge[edgenum] = E;
head[u] = edgenum++;
}
int DFN[N], Low[N], Stack[N], top, Time;
int taj;
int Belong[N];
bool Instack[N];
vector<int> bcc[N];
int in[N*2],out[N*2];
void tarjan(int u ,int fa){
DFN[u] = Low[u] = ++ Time ;
Stack[top ++ ] = u ;
Instack[u] = 1 ;
for (int i = head[u] ; ~i ; i = edge[i].nex ){
int v = edge[i].to ;
if(DFN[v] == -1)
{
tarjan(v , u) ;
Low[u] = min(Low[u] ,Low[v]) ;
if(DFN[u] < Low[v])
{
edge[i].sign = 1;
}
}
else if(Instack[v]) Low[u] = min(Low[u] ,DFN[v]) ;
}
if(Low[u] == DFN[u]){
int now;
taj ++ ; bcc[taj].clear();
do{
now = Stack[-- top] ;
Instack[now] = 0 ;
Belong [now] = taj ;
bcc[taj].push_back(now);
}while(now != u) ;
}
}
void tarjan_init(int all){
memset(DFN, -1, sizeof(DFN));
memset(Instack, 0, sizeof(Instack));
top = Time = taj = 0;
for(int i=1;i<=all;i++)if(DFN[i]==-1 )tarjan(i, i);
}
vector<int>G[N];
int du[N];
void suodian(){
memset(du, 0, sizeof(du));
for(int i = 1; i <= taj; i++)G[i].clear();
for(int i = 0; i < edgenum; i++){
int u = Belong[edge[i].from], v = Belong[edge[i].to];
if(u!=v)G[u].push_back(v), du[v]++;
}
}
void init(){memset(head, -1, sizeof(head)); edgenum=0;}
int main()
{
int u,v,i,j,T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
for(i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
}
tarjan_init(n);
if(taj==1)
printf("0\n");
else
{
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for(i = 1; i <= n; i ++)
{
for(int k = head[i]; k != -1; k = edge[k].nex)
{
j = edge[k].to;
if(Belong[i] != Belong[j])
out[Belong[i]] ++, in[Belong[j]] ++;
}
}
int root = 0,leaf = 0;
for(i = 1; i <= taj; i ++)
{
if(in[i] == 0) root ++;
if(out[i] == 0) leaf ++;
}
printf("%d\n",leaf > root ? leaf : root);
}
}
return 0;
}