HDU - 2767(强连通分量)
求一个有向图里加最少的边使得任意两点可达。。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main
{
static int n,m;
static int maxx=20005;
static int maxn=50005;
static int head[]=new int[maxx];
static int next[]=new int[maxn];
static int to[]=new int[maxn];
static int cnt;
static void addEdge(int x,int y)
{
to[++cnt]=y;next[cnt]=head[x];head[x]=cnt;
}
static int DFN[]=new int[maxx];
static int low[]=new int[maxx];
static boolean inS[]=new boolean[maxx];
static int be[]=new int[maxx];
static int index;
static int st[]=new int[maxx];
static int p=0;
static int count;
static void tarjan(int v)
{
DFN[v]=low[v]=++index;
st[++p]=v;
inS[v]=true;
for(int i=head[v];i>0;i=next[i])
{
int u=to[i];
if(DFN[u]==0)
{
tarjan(u);
low[v]=Math.min(low[v], low[u]);
}
else
if(inS[u])
low[v]=Math.min(low[v], DFN[u]);
}
if(DFN[v]==low[v])
{
count++;
while(st[p]!=v)
{
be[st[p]]=count;
inS[st[p]]=false;
p--;
}
be[st[p]]=count;
inS[st[p]]=false;
p--;
}
}
static int in[]=new int[maxx];
static int out[]=new int[maxx];
static int work()
{
//System.out.println("haha");
if(count==1)
return 0;
for(int i=1;i<=n;i++)
{
for(int j=head[i];j>0;j=next[j])
{
if(be[i]!=be[to[j]])
{
out[be[i]]++;
in[be[to[j]]]++;
}
}
}
int inNum=0,outNum=0;
for(int i=1;i<=count;i++)
{
inNum+=in[i]==0?1:0;
outNum+=out[i]==0?1:0;
}
return Math.max(inNum, outNum);
}
static void init()
{
Arrays.fill(head, 0);
Arrays.fill(in, 0);
Arrays.fill(out, 0);
Arrays.fill(DFN, 0);
cnt=0;
index=0;
count=0;
}
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
int t=sc.nextInt();
while(t-->0)
{
init();
n=sc.nextInt();
m=sc.nextInt();
while(m-->0)
addEdge(sc.nextInt(),sc.nextInt());
for(int i=1;i<=n;i++)
if(DFN[i]==0)
tarjan(i);
System.out.println(work());
}
}
}