Given a directed graph G, consider the following transformation. First, create a new graph T(G) to have the same vertex set as G. Create a directed edge between two vertices u and v in T(G) if and only if there is a path between u and v in G that follows the directed edges only in the forward direction. This graph T(G) is often called the transitive closure of G.
We define a clique in a directed graph as a set of vertices U such that for any two vertices u and v in U, there is a directed edge either from u to v or from v to u (or both). The size of a clique is the number of vertices in the clique.
The number of cases is given on the first line of input. Each test case describes a graph G. It begins with a line of two integers n and m, where 0 ≤ n ≤ 1000 is the number of vertices of G and 0 ≤ m ≤ 50,000 is the number of directed edges of G. The vertices of G are numbered from 1 to n. The following m lines contain two distinct integers u and v between 1 and n which define a directed edge from u tov in G.
For each test case, output a single integer that is the size of the largest clique in T(G).
1 5 5 1 2 2 3 3 1 4 1 5 2
4Zachary Friggstad
思路:强连通缩点后,个缩后的点一个权值,就是当前点包含点的个数,然后搜条权值最大的路径就是个水DP了。
159MS
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> using namespace std; const int mm=1000+9; const int mn=5e4+9; int head[mm],edge; class node { public:int v,next; }e[mn],cun[mn]; int m,n; void add(int u,int v) { e[edge].v=v;e[edge].next=head[u];head[u]=edge++; } void data() { memset(head,-1,sizeof(head));edge=0; } int bcc_no,dfs_clock,e_to[mm],dfn[mm]; int stak[mm],top,cost[mm]; int tarjan(int u) { stak[++top]=u; int lowv,lowu,v; dfn[u]=lowu=++dfs_clock; for(int i=head[u];~i;i=e[i].next) {v=e[i].v; if(!dfn[v]) { lowv=tarjan(v); lowu=min(lowu,lowv); } else if(!e_to[v]) lowu=min(dfn[v],lowu); } if(dfn[u]==lowu) { bcc_no++;int num=0; while(1) { ++num; v=stak[top--];e_to[v]=bcc_no; if(v==u)break; } cost[bcc_no]=num; } return lowu; } void find_gcc() { memset(dfn,0,sizeof(dfn)); memset(e_to,0,sizeof(e_to)); bcc_no=top=dfs_clock=0; for(int i=1;i<=n;++i) if(!dfn[i])tarjan(i); } int dp[mm]; int dfs(int u) { int v; if(dp[u])return dp[u]; for(int i=head[u];~i;i=e[i].next) { v=e[i].v; dp[u]=max(dp[u],dfs(v)); } dp[u]+=cost[u]; return dp[u]; } int solve() { data();int u,v; for(int i=0;i<m;++i) { u=e_to[cun[i].next];v=e_to[cun[i].v]; if(u^v) { add(u,v); } } int ans=0; memset(dp,0,sizeof(dp)); for(int i=1;i<=bcc_no;++i) {ans=max(ans,dfs(i)); ///cout<<i<<" "<<dp[i]<<endl; } return ans; } int main() { int cas,a,b; while(~scanf("%d",&cas)) { while(cas--) { data(); scanf("%d%d",&n,&m); for(int i=0;i<m;++i) { scanf("%d%d",&a,&b); cun[i].next=a;cun[i].v=b; if(a==b)continue; add(a,b); } find_gcc(); int ans=solve(); if(n==0)ans=0; printf("%d\n",ans); } } return 0; }