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 betweenu and v in G that follows the directed edges only in the forward direction. This graph T(G) is often called thetransitive 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 to v 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 Friggsta
先把强连通分量缩点后得到scc图,每个scc节点的权等于他的节点数,因为scc是dag图,所以可以用dp求解
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define CLR(vis,pos) memset(vis,pos,sizeof(vis))
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LINF 1000000000000000000LL
#define eps 1e-8
const int maxn=1234;
const int maxm=55555;
struct node{
int to,next;
}e[maxm];
int head[maxn],edge;
int low[maxn],dfn[maxn],stk[maxn],belong[maxn];
int tsp,top;
int scc;
bool in_stk[maxn];
int num[maxn];
void init(){
edge=0;
CLR(head,-1);
}
void addedge(int u,int v){
e[edge].to=v;
e[edge].next=head[u];
head[u]=edge++;
}
void tarjan(int u){
int v;
low[u]=dfn[u]=++tsp;
stk[top++]=u;
in_stk[u]=true;
for(int i=head[u];~i;i=e[i].next){
v=e[i].to;
if(!dfn[v]){
tarjan(v);
if(low[u]>low[v]) low[u]=low[v];
}
else{
if(in_stk[v] && low[u]>dfn[v])
low[u]=dfn[v];
}
}
if(low[u]==dfn[u]){
scc++;
do{
v=stk[--top];
in_stk[v]=false;
belong[v]=scc;
num[scc]++;
}while(v!=u);
}
}
void solve(int N){
CLR(dfn,0);
CLR(in_stk,false);
CLR(num,0);
tsp=top=scc=0;
FOR(i,1,N)
if(!dfn[i])
tarjan(i);
}
vector<int> g[maxn];
int dp[maxn];
int dfs(int u){
if(dp[u]) return dp[u];
if(g[u].size()==0) return dp[u]=num[u];
int tmp=0;
REP(i,g[u].size())
tmp=max(tmp,dfs(g[u][i]));
return dp[u]=tmp+num[u];
}
int main()
{
int _;
cin>>_;
int n,m;
REP(cas,_){
init();
cin>>n>>m;
int u,v;
REP(i,m){
scanf("%d%d",&u,&v);
if(u==v) continue;
addedge(u,v);
}
solve(n);
FOR(i,0,n) g[i].clear();
FOR(u,1,n){
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].to;
if(belong[u]!=belong[v])
g[belong[u]].PB(belong[v]);
}
}
int ans=0;
CLR(dp,0);
FOR(i,1,scc)
ans=max(ans,dfs(i));
cout<<ans<<endl;
}
return 0;
}