UVa11324 The Largest Clique(强连通分量+缩点+记忆化搜索)
题目给一张有向图G,要在其传递闭包T(G)上删除若干点,使得留下来的所有点具有单连通性,问最多能留下几个点。
其实这道题在T(G)上的连通性等同于在G上的连通性,所以考虑G就行了。
那么问题就简单了,强连通分量缩点,强连通分量必定要一起留下,从入度0到出度0的强连通分量找到一条包含最多点的通路即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define MAXN 1111 6 #define MAXM 55000 7 struct Edge{ 8 int u,v,next; 9 }edge[MAXM]; 10 int NE,head[MAXN]; 11 void addEdge(int u,int v){ 12 edge[NE].u=u; edge[NE].v=v; edge[NE].next=head[u]; 13 head[u]=NE++; 14 } 15 int top,stack[MAXN]; 16 bool instack[MAXN]; 17 int dn,dfn[MAXN],low[MAXN]; 18 int bn,belong[MAXN],size[MAXN]; 19 void tarjan(int u){ 20 dfn[u]=low[u]=++dn; 21 stack[++top]=u; instack[u]=1; 22 for(int i=head[u]; i!=-1; i=edge[i].next){ 23 int v=edge[i].v; 24 if(dfn[v]==0){ 25 tarjan(v); 26 low[u]=min(low[u],low[v]); 27 }else if(instack[v]){ 28 low[u]=min(low[u],dfn[v]); 29 } 30 } 31 if(low[u]==dfn[u]){ 32 int v; ++bn; 33 do{ 34 v=stack[top--]; 35 instack[v]=0; 36 belong[v]=bn; 37 ++size[bn]; 38 }while(u!=v); 39 } 40 } 41 int d[MAXN]; 42 int dfs(int u){ 43 if(d[u]) return d[u]; 44 int res=0; 45 for(int i=head[u]; i!=-1; i=edge[i].next){ 46 int v=edge[i].v; 47 res=max(res,dfs(v)); 48 } 49 return d[u]=res+size[u]; 50 } 51 int main(){ 52 int t,n,m,a,b; 53 scanf("%d",&t); 54 while(t--){ 55 scanf("%d%d",&n,&m); 56 NE=0; 57 memset(head,-1,sizeof(head)); 58 while(m--){ 59 scanf("%d%d",&a,&b); 60 addEdge(a,b); 61 } 62 top=dn=bn=0; 63 memset(dfn,0,sizeof(dfn)); 64 memset(instack,0,sizeof(instack)); 65 memset(size,0,sizeof(size)); 66 for(int i=1; i<=n; ++i){ 67 if(dfn[i]==0) tarjan(i); 68 } 69 int tmp=NE; NE=0; 70 memset(head,-1,sizeof(head)); 71 for(int i=0; i<tmp; ++i){ 72 int u=belong[edge[i].u],v=belong[edge[i].v]; 73 if(u==v) continue; 74 addEdge(u,v); 75 } 76 memset(d,0,sizeof(d)); 77 int res=0; 78 for(int i=1; i<=bn; ++i){ 79 res=max(res,dfs(i)); 80 } 81 printf("%d\n",res); 82 } 83 return 0; 84 }