UVa11324 - The Largest Clique(DAG+DP+SCC)

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

强连通分量缩点+DAG的DP

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
const int maxn = 1000+10;
const int maxm = 50000+10;
struct edge{
    int v,nxt;
}e[maxm];

int head[maxn];
int nume;
stack<int> S;
int dfs_clk;
int scc_no;
int dfn[maxn],lown[maxn],sccno[maxn];
int dp[maxn];
int n,m;
int num[maxn];
vector<int> G[maxn];
void init(){
    while(!S.empty()) S.pop();
    memset(head,0,sizeof head);
    memset(num,0,sizeof num);
    memset(dp,-1,sizeof dp);
    for(int i = 0; i <= n; i++){
        G[i].clear();
    }
    nume = 1;
    dfs_clk = 0;
    scc_no = 0;
    memset(dfn,0,sizeof dfn);
    memset(sccno,0,sizeof sccno);
}
void addedge(int u,int v){
    e[++nume].nxt = head[u];
    e[nume].v = v;
    head[u] = nume;
}

void dfs(int u){
    dfn[u] = lown[u] = ++dfs_clk;
    S.push(u);
    for(int i = head[u]; i ; i = e[i].nxt){
        int v = e[i].v;
        if(!dfn[v]){
            dfs(v);
            lown[u] = min(lown[u],lown[v]);
        }
        else if(!sccno[v]){
            lown[u] = min(lown[u],dfn[v]);
        }
    }
    if(lown[u] == dfn[u]){
        scc_no++;
        while(true){
            int x = S.top(); S.pop();
            sccno[x] = scc_no;
            if(x==u) break;
        }
    }
}

void find_scc(){
    for(int i = 1; i <= n; i++){
        if(!dfn[i])
            dfs(i);
    }
}

int dfs_dp(int x){
    if(dp[x] != -1) return dp[x];
    int ret = 0;
    for(int i = 0; i < G[x].size(); i++){
        int d = G[x][i];
        ret = max(ret,dfs_dp(d)+num[x]);
    }
    if(G[x].size()==0) ret = num[x];
    return dp[x] = ret;
}

void solve(){
    for(int i = 1; i <= n; i++){
        int d = sccno[i];
        num[d]++;
        for(int j = head[i]; j; j = e[j].nxt){
            if(d!=sccno[e[j].v])
                G[d].push_back(sccno[e[j].v]);
        }
    }
    int ret = 0;
    for(int i = 1; i <= scc_no; i++){
        ret = max(ret,dfs_dp(i));
    }
    printf("%d\n",ret);

}
int main(){

    int ncase;
    cin >> ncase;
    while(ncase--){
        scanf("%d%d",&n,&m);
        init();
        while(m--){
            int a,b;
            scanf("%d%d",&a,&b);
            addedge(a,b);
        }
        find_scc();
        solve();

    }
    return 0;
}

UVa11324 - The Largest Clique(DAG+DP+SCC)

时间: 2024-10-22 12:16:33

UVa11324 - The Largest Clique(DAG+DP+SCC)的相关文章

uva11324 The Largest Clique --- 强连通+dp

给一个有向图G,求一个子图要求其中任意两点至少有一边可达, 问这个子图中最多含多少个顶点. 首先找SCC缩点建图,每个点的权值就是该点包含点的个数. 要求其中任意两点可达,实际上所有边只能同方向,不然一定有两点不可达, 这样题目又转换成求DAG图最长路的问题了. 然后从入度为0的点开始记忆化搜索,dp[i]表示以i为根最多包含多少点. #include <iostream> #include <cstring> #include <string> #include &l

UVA11324 The Largest Clique[强连通分量 缩点 DP]

UVA - 11324 The Largest Clique 题意:求一个节点数最大的节点集,使任意两个节点至少从一个可以到另一个 同一个SCC要选一定全选 求SCC 缩点建一个新图得到一个DAG,直接DP行了 这个新图不需要判重边,重边就是真实存在 // // main.cpp // 最大团 // // Created by Candy on 02/11/2016. // Copyright © 2016 Candy. All rights reserved. // #include <ios

UVA11324 The Largest Clique —— 强连通分量 + 缩点 + DP

题目链接:https://vjudge.net/problem/UVA-11324 题解: 代码一: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <sta

UVA-11324 The Largest Clique 【有向图强连通+缩点+DP】

题目链接:https://vjudge.net/problem/UVA-11324 题目大意:给定一张有向图G,求一个结点数最大的结点集,集合中每两个点都至少有一条路径相连(方向任意). 题解: 易知如果一个点被选择,则它所在强连通分量中的其他点也一定要选,如果不选,则其他点也不可选,因此先求出强连通分量,利用缩点创建出另一张有向图G2,每个结点的权值就是该强连通分量的结点数,再DP求解. 代码: 1 #include<bits/stdc++.h> 2 using namespace std;

UVA - 11324 The Largest Clique (DAG + 强连通分量)

题目大意:给出一张有向图G,求一个结点数最大的结点集,使得该点集中任意两个结点u和v满足: 要么u可到达v,要么v可以到达u(u和v互相可达也可以) 解题思路:u和v相互可达的时候,就是两个结点在同一个强连通分量内的时候 首先要保证集合里面的点可达:强连通分量就满足集合内的点都相互可达.所以第一件事就是找出所有的强连通分量,并统计出每个强连通分量内的结点数 然后找出每个强连通分量之间的关系,也就是找出两个强连通分量之间的桥,连接可连接的强连通分量 最后将每个强连通分量收缩,得到SCC图.此时的S

UVAoj 11324 - The Largest Clique(tarjan + dp)

题意:给定一个有向图,寻找一个点数最大集合,使得这个集合中的任意两个点 u,v, 都有u->v 或者 v->u 或者u<==>v 思路:首先将强连通分量通过tarjan算法求出来,然后进行缩点,也就是每一个缩点 所组成的图就是一个DAG图!令每一个点的权值就是这个缩点所包含节点(也就是对应的 强连通分量的节点数目),因为强连通分量的任意的两个节点都是相互可达的,那么这个 缩点要么选要么不选,问题就转换成了DAG图上的最长路径! 1 #include<iostream>

UVA11324 The Largest Clique,有向图,最大团的结点数

点击打开链接 有向图 把强联通分量缩点后得到一个DAG,然后DP. </pre><pre name="code" class="cpp">#include <cstdio> #include <cstring> #include <algorithm> #include <stack> #include <vector> #include <queue> using na

uva 11324 The Largest Clique(强连通分量缩点+DAG动态规划)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299 题意:输入n和m,有n个点和m条有向边,求出一个节点集合包括的节点个数最多,而且该节点内的不论什么两点a,b,要么a能到达b,要么b能到达a,要么a和b互相到达. 思路:强连通分量缩点形成有向无环图DAG,把缩点后的每一个点的权值置为该强连通分量的节点个

UVA - 11324 The Largest Clique 强连通缩点+记忆化dp

题目要求一个最大的弱联通图. 首先对于原图进行强连通缩点,得到新图,这个新图呈链状,类似树结构. 对新图进行记忆化dp,求一条权值最长的链,每个点的权值就是当前强连通分量点的个数. /* Tarjan算法求有向图的强连通分量set记录了强连通分量 Col记录了强连通分量的个数. */ #include <iostream> #include<cstring> #include<cstdio> #include<string> #include<algo