Problem B: The Largest Clique
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).
Sample input
1 5 5 1 2 2 3 3 1 4 1 5 2
Output for sample input
4
Zachary 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;
}