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

题意:给定一个有向图,求一个最大的结点集,使得任意两个结点,要么 u 能到 v,要么 v 到u。

析:首先,如果是同一个连通分量,那么要么全选,要么全不选,然后我们就可以先把强连通分量先求出来,然后缩成一个点,然后该图就成了一个DAG,然后就可以直接用DP来做了。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
#define sz size()
#define pu push_up
#define pd push_down
#define cl clear()
#define all 1,n,1
#define FOR(x,n)  for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e15;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1000 + 50;
const LL mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c) {
  return r >= 0 && r < n && c >= 0 && c < m;
}

vector<int> G[maxn];
int pre[maxn], lowlink[maxn], sccno[maxn];
int dfs_cnt, scc_cnt;
stack<int> S;

void dfs(int u){
  pre[u] = lowlink[u] = ++dfs_cnt;
  S.push(u);
  for(int i = 0; i < G[u].sz; ++i){
    int v = G[u][i];
    if(!pre[v]){
      dfs(v);
      lowlink[u] = min(lowlink[u], lowlink[v]);
    }
    else if(!sccno[v])
      lowlink[u] = min(lowlink[u], pre[v]);
  }
  if(lowlink[u] == pre[u]){
    ++scc_cnt;
    while(1){
      int x = S.top();  S.pop();
      sccno[x] = scc_cnt;
      if(x == u)  break;
    }
  }
}

void find_scc(int n){
  dfs_cnt = scc_cnt = 0;
  ms(pre, 0);  ms(sccno, 0);
  for(int i = 1; i <= n; ++i)
    if(!pre[i])  dfs(i);
}

vector<int> g[maxn];
int num[maxn];

int dp[maxn];
int ans;
bool vis[maxn];

void dfs1(int u){
  dp[u] = 0;
  for(int i = 0; i < g[u].sz; ++i){
    int v = g[u][i];
    dfs1(v);
    dp[u] = max(dp[u], dp[v]);
  }
  dp[u] += num[u];
  ans = max(ans, dp[u]);
}

int main(){
  int T;  cin >> T;
  while(T--){
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; ++i)  G[i].cl, g[i].cl;
    for(int i = 0; i < m; ++i){
      int u, v;
      scanf("%d %d", &u, &v);
      G[u].pb(v);
    }
    find_scc(n);  ms(num, 0);
    ms(vis, 0);
    for(int i = 1; i <= n; ++i)  ++num[sccno[i]];
    for(int i = 1; i <= n; ++i)
      for(int j = 0; j < G[i].sz; ++j){
        int v = G[i][j];
        if(sccno[i] != sccno[v]){
          g[sccno[i]].pb(sccno[v]);
          vis[sccno[v]] = 1;
        }
      }
    ans = 0;
    for(int i = 1; i <= scc_cnt; ++i)
      if(!vis[i])  dfs1(i);
    printf("%d\n", ans);
  }
  return 0;
}

  

时间: 2024-08-06 11:58:15

UVa 11324 The Largest Clique (强连通分量+DP)的相关文章

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)

题目: 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

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

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

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

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

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(图论-tarjan,动态规划)

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