Uva--11324--The Largest Clique【有向图强连通分量+最大团】

链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=25&problem=2299&mosmsg=Submission+received+with+ID+14404690

题意:一个有向图,找一个最大的点集使得任意两点u、v间都存在一条路(单向或双向),问这个点集最大是多少

思路:强连通分量缩点后得到SCC图,使SCC结点的权等于它的节点个数,找一条路径使得权值和最大即可,找路径用dp记忆化搜索

#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 1010
#define eps 1e-7
#define INF 0x3F3F3F3F      //0x7FFFFFFF
#define LLINF 0x7FFFFFFFFFFFFFFF
#define seed 1313131
#define MOD 1000000007
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

const int maxm = 50010;
struct node{
    int u, v, next;
}edge[maxm], edge1[maxm];
int Stack[MAXN];
int head[MAXN], head1[MAXN], dfn[MAXN], low[MAXN], sccno[MAXN], scc_elem[MAXN];
int scc_cnt, id, cnt, cnt1, top, n, m;
int dp[MAXN];
void add_edge(int u, int v, node edge[], int head[], int &cnt){
    edge[cnt].u = u;
    edge[cnt].v = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}
void tarjin(int u){
    int i, j;
    dfn[u] = low[u] = ++id;
    Stack[top++] = u;
    for(i = head[u]; i != -1; i = edge[i].next){
        int v = edge[i].v;
        if(dfn[v] == -1){
            tarjin(v);
            low[u] = min(low[u], low[v]);
        }
        else if(!sccno[v]){
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(low[u] == dfn[u]){
        scc_cnt++;
        int temp;
        do{
            temp = Stack[--top];
            sccno[temp] = scc_cnt;
        }while(temp != u);
    }
}
int dfs_DAG(int u){
    if(dp[u] > 0)   return dp[u];
    dp[u] = scc_elem[u];
    for(int i = head1[u]; i != -1; i = edge1[i].next){
        int v = edge1[i].v;
        dp[u] = max(dp[u], scc_elem[u] + dfs_DAG(v));
    }
    return dp[u];
}
int main(){
    int i, j, t;
    scanf("%d", &t);
    while(t--){
        scanf("%d%d", &n, &m);
        cnt = cnt1 = scc_cnt = id = top = 0;
        memset(head, -1, sizeof(head));
        memset(head1, -1, sizeof(head1));
        memset(dfn, -1, sizeof(dfn));
        memset(sccno, 0, sizeof(sccno));
        memset(scc_elem, 0, sizeof(scc_elem));
        for(i = 0; i < m; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            add_edge(u, v, edge, head, cnt);
        }
        for(i = 1; i <= n; i++){
            if(dfn[i] == -1)    tarjin(i);
        }
        for(i = 1; i <= n; i++){
            int x = sccno[i];
            scc_elem[x]++;
        }
        for(i = 0; i < cnt; i++){
            int u = edge[i].u;
            int v = edge[i].v;
            if(sccno[u] != sccno[v]){
                add_edge(sccno[u], sccno[v], edge1, head1, cnt1);
            }
        }
        memset(dp, 0, sizeof(dp));
        int ans = 0;
        for(i = 1; i <= scc_cnt; i++){
            ans = max(ans, dfs_DAG(i));
        }
        printf("%d\n", ans);
    }
    return 0;
}
时间: 2024-10-29 18:50:53

Uva--11324--The Largest Clique【有向图强连通分量+最大团】的相关文章

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

UVA 11324 - The Largest Clique 题目链接 题意:给定一个有向图,要求找一个集合,使得集合内任意两点(u, v)要么u能到v,要么v能到u,问最大能选几个点 思路:强连通分量,构造出scc之后,缩点,每个点的权值是集合点个数,然后做一遍dag找出最大权值路径即可 代码: #include <cstdio> #include <cstring> #include <vector> #include <stack> #include

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

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

UVA 11324 The Largest Clique (强连通缩点 + DAG最长路)

链接 : http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=30726 题意 : 有向图G,求一个最大的点集,使得点集中任意两个节点u和v,满足 要么u可以到达v,要么v可以到达u,或者u和v可以相互到达. 可以强连通缩点成一张DAG,以为每个强连通分量要么选要么不选.求DAG上的最长路 二次建图 用了2种不同的方法,也分别用了记忆花搜索DP和直接递推DP vector建图和记忆化搜索: #include <algorithm

Uva 11324 The Largest Clique【强连通 DAG动规 spfa】

白书上的例题 做一遍tarjan后,缩点,每一个scc节点的权为它的结点数,做一次DAG上的动规,求出路径上的最大点权和,就可以了 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<stack> 6 #include<vector> 7 using namespace std; 8 9 const i

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

UVA 11324 The Largest Clique (强连通分量缩点,图DP)

题目: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299 题意: 给你一个有向图,求一个点集合的最大大小,使得此点集合中对于任意点对(u,v),有从u到v或者从v到u的边 方法: 先找强连通分量缩点,每个强连通分量显然满足条件,然后在缩点后的图中找到一条权值最大的路径,权值为此路径的点权之和,点权为这个

UVa 11324 The Largest Clique (强连通分量+DP)

题意:给定一个有向图,求一个最大的结点集,使得任意两个结点,要么 u 能到 v,要么 v 到u. 析:首先,如果是同一个连通分量,那么要么全选,要么全不选,然后我们就可以先把强连通分量先求出来,然后缩成一个点,然后该图就成了一个DAG,然后就可以直接用DP来做了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #i

UVA - 11324 The Largest Clique (强连通缩点+dp)

题目链接 题意:从有向图G中找到一个最大的点集,使得该点集中任意两个结点u,v满足u可达v或v可达u. 解法:先把同处于一个强连通分量中的结点合并(缩点),得到一张DAG图,在DAG上dp即可. 感觉自己的建图写得好丑啊,一直在纠结用数组还是结构体~~ 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 const int N=1e5+10; 5 int head[N],nxt[N],to[N],ne,n,m; 6 void addedge