UVA 11324 The Largest Clique 強連通縮點+DP

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章