UVA - 11324 |
题意:求一个节点数最大的节点集,使任意两个节点至少从一个可以到另一个
同一个SCC要选一定全选
求SCC 缩点建一个新图得到一个DAG,直接DP行了
这个新图不需要判重边,重边就是真实存在
// // main.cpp // 最大团 // // Created by Candy on 02/11/2016. // Copyright © 2016 Candy. All rights reserved. // #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #define C(x) memset(x,0,sizeof(x)) using namespace std; const int N=1e3+5,M=5e4+5; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int T,n,m,u,v; struct edge{ int v,ne; }e[M]; int h[N],cnt=0; inline void ins(int u,int v){ cnt++; e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt; } int dfn[N],low[N],belong[N],dfc,scc,size[N]; int st[N],top; void dfs(int u){ dfn[u]=low[u]=++dfc; st[++top]=u; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(!dfn[v]){ dfs(v); low[u]=min(low[u],low[v]); }else if(!belong[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]){ scc++; while(true){ int x=st[top--]; belong[x]=scc; size[scc]++; if(x==u) break; } } } void SCC(){ dfc=scc=0; C(dfn);C(low);C(belong);C(size); top=0; for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i); } edge es[N]; int hs[N],cs=0; inline void inss(int u,int v){ cs++; es[cs].v=v;es[cs].ne=hs[u];hs[u]=cs; } void buildGraph(){ cs=0; C(hs); for(int u=1;u<=n;u++){ int a=belong[u]; for(int i=h[u];i;i=e[i].ne){ int b=belong[e[i].v]; if(a!=b) inss(a,b); } } } int f[N]; int dp(int u){ if(f[u]!=-1) return f[u]; f[u]=size[u]; int mx=0; for(int i=hs[u];i;i=es[i].ne){ int v=es[i].v;//printf("dp %d v %d ",u,v); mx=max(mx,dp(v)); } return f[u]+=mx; } int main(int argc, const char * argv[]) { T=read(); while(T--){ n=read();m=read(); cnt=0;memset(h,0,sizeof(h)); for(int i=1;i<=m;i++){u=read();v=read();ins(u,v);} SCC(); buildGraph(); memset(f,-1,sizeof(f)); int ans=0; for(int i=1;i<=scc;i++){ if(f[i]==-1) dp(i); ans=max(ans,f[i]); } printf("%d ",ans); } return 0; }