题目链接:https://vjudge.net/problem/UVA-11324

题解:

题意:给出一张有向图,求一个结点数最大的结点集,使得任意两个结点u、v,要么u能到达v, 要么v能到达u(u和v也可以互相到达)。

1.可知在一个强连通分量中,任意两个点都可以互相到达。那么我们就对每个强连通分量进行缩点,并记录每个分量的结点个数。

2.缩点之后,就是一张有向无环图了,这时就转化为求:从有向无环图中找出一条权值之和最大的路径。简单的记忆化搜索即可实现。

前向星建图 + 前向星重建:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXM = 5e4+;
const int MAXN = 1e3+; struct Edge
{
int to, next;
}edge[MAXM], edge0[MAXM]; //edge为初始图, edge0为重建图
int tot, head[MAXN], tot0, head0[MAXN]; int Index, dfn[MAXN], low[MAXN];
int top, Stack[MAXN], instack[MAXN];
int scc, belong[MAXN], num[MAXN];
int dp[MAXN]; void addedge(int u, int v, Edge edge[], int head[], int &tot)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} void Tarjan(int u)
{
dfn[u] = low[u] = ++Index;
Stack[top++] = u;
instack[u] = true;
for(int i = head[u]; i!=-; i = edge[i].next)
{
int v = edge[i].to;
if(!dfn[v])
{
Tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(instack[v])
low[u] = min(low[u], dfn[v]);
} if(dfn[u]==low[u])
{
int v;
scc++;
do
{
v = Stack[--top];
instack[v] = false;
belong[v] = scc;
num[scc]++;
}while(v!=u);
}
} int dfs(int u)
{
if(dp[u]!=-) return dp[u];
dp[u] = num[u];
for(int i = head0[u]; i!=-; i = edge0[i].next)
{
int v = edge0[i].to;
dp[u] = max(dp[u], num[u]+dfs(v));
}
return dp[u];
} void init()
{
tot = tot0 = ;
memset(head, -, sizeof(head));
memset(head0, -, sizeof(head0)); Index = top = ;
memset(dfn, , sizeof(dfn));
memset(low, , sizeof(low));
memset(instack, , sizeof(instack)); scc = ;
memset(num, , sizeof(num));
memset(dp, -, sizeof(dp));
} int main()
{
int n, m, T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
init();
for(int i = ; i<=m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
addedge(u, v, edge, head, tot);
} for(int i = ; i<=n; i++)
if(!dfn[i])
Tarjan(i); for(int u = ; u<=n; u++) //重建建图
for(int i = head[u]; i!=-; i = edge[i].next)
{
int tmpu = belong[u];
int tmpv = belong[edge[i].to];
if(tmpu!=tmpv)
addedge(tmpu, tmpv, edge0, head0, tot0);
} int ans = ;
for(int i = ; i<=scc; i++)
if(dp[i]==-)
ans = max(ans, dfs(i)); printf("%d\n", ans);
}
}

前向星建图 + vector重建:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const int MAXM = 5e4+;
const int MAXN = 1e3+; struct Edge
{
int to, next;
}edge[MAXM];
int tot, head[MAXN];
vector<int>g[MAXN]; int Index, dfn[MAXN], low[MAXN];
int top, Stack[MAXN], instack[MAXN];
int scc, belong[MAXN], num[MAXN];
int dp[MAXN]; void addedge(int u, int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} void Tarjan(int u)
{
dfn[u] = low[u] = ++Index;
Stack[top++] = u;
instack[u] = true;
for(int i = head[u]; i!=-; i = edge[i].next)
{
int v = edge[i].to;
if(!dfn[v])
{
Tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(instack[v])
low[u] = min(low[u], dfn[v]);
} if(dfn[u]==low[u])
{
int v;
scc++;
do
{
v = Stack[--top];
instack[v] = false;
belong[v] = scc;
num[scc]++;
}while(v!=u);
}
} int dfs(int u)
{
if(dp[u]!=-) return dp[u];
dp[u] = num[u];
for(int i = ; i<g[u].size(); i++)
{
int v = g[u][i];
dp[u] = max(dp[u], num[u]+dfs(v));
}
return dp[u];
} void init(int n)
{
tot = ;
memset(head, -, sizeof(head)); Index = top = ;
memset(dfn, , sizeof(dfn));
memset(low, , sizeof(low));
memset(instack, , sizeof(instack)); scc = ;
memset(num, , sizeof(num));
memset(dp, -, sizeof(dp));
for(int i = ; i<=n; i++)
g[i].clear();
} int main()
{
int n, m, T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
init(n);
for(int i = ; i<=m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
addedge(u, v);
} for(int i = ; i<=n; i++)
if(!dfn[i])
Tarjan(i); for(int u = ; u<=n; u++)
for(int i = head[u]; i!=-; i = edge[i].next)
{
int tmpu = belong[u];
int tmpv = belong[edge[i].to];
if(tmpu!=tmpv)
g[tmpu].push_back(tmpv);
} int ans = ;
for(int i = ; i<=scc; i++)
if(dp[i]==-)
ans = max(ans, dfs(i)); printf("%d\n", ans);
}
}

vector建图 + vector重建:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const int MAXN = 1e3+; vector<int>G[MAXN], g[MAXN]; int Index, dfn[MAXN], low[MAXN];
int top, Stack[MAXN], instack[MAXN];
int scc, belong[MAXN], num[MAXN];
int dp[MAXN]; void Tarjan(int u)
{
dfn[u] = low[u] = ++Index;
Stack[top++] = u;
instack[u] = true;
for(int i = ; i<G[u].size(); i++)
{
int v = G[u][i];
if(!dfn[v])
{
Tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(instack[v])
low[u] = min(low[u], dfn[v]);
} if(dfn[u]==low[u])
{
int v;
scc++;
do
{
v = Stack[--top];
instack[v] = false;
belong[v] = scc;
num[scc]++;
}while(v!=u);
}
} int dfs(int u)
{
if(dp[u]!=-) return dp[u];
dp[u] = num[u];
for(int i = ; i<g[u].size(); i++)
{
int v = g[u][i];
dp[u] = max(dp[u], num[u]+dfs(v));
}
return dp[u];
} void init(int n)
{
Index = top = ;
memset(dfn, , sizeof(dfn));
memset(low, , sizeof(low));
memset(instack, , sizeof(instack)); scc = ;
memset(num, , sizeof(num));
memset(dp, -, sizeof(dp));
for(int i = ; i<=n; i++)
{
G[i].clear();
g[i].clear();
}
} int main()
{
int n, m, T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
init(n);
for(int i = ; i<=m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
} for(int i = ; i<=n; i++)
if(!dfn[i])
Tarjan(i); for(int u = ; u<=n; u++)
for(int i = ; i<G[u].size(); i++)
{
int tmpu = belong[u];
int tmpv = belong[G[u][i]];
if(tmpu!=tmpv)
g[tmpu].push_back(tmpv);
} int ans = ;
for(int i = ; i<=scc; i++)
if(dp[i]==-)
ans = max(ans, dfs(i)); printf("%d\n", ans);
}
}

UVA11324 The Largest Clique —— 强连通分量 + 缩点 + DP的更多相关文章

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

    UVA - 11324 The Largest Clique 题意:求一个节点数最大的节点集,使任意两个节点至少从一个可以到另一个 同一个SCC要选一定全选 求SCC 缩点建一个新图得到一个DAG,直 ...

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

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=sh ...

  3. UVA 11324 The Largest Clique(强连通分量+缩点DAG的DP)

    题意:给定一个有向图,求出一个最大的结点集,这个节点集中的随意两个点之间至少一个能到达还有一个点. 思路:假设一个点在这个节点集中,那么它所在的强连通分量中的点一定所有在这个节点集中,反之亦然, 求出 ...

  4. UVA11324 The Largest Clique (强连通缩点+DP最长路)

    <题目链接> 题目大意: 给你一张有向图 G,求一个结点数最大的结点集,使得该结点集中的任意两个结点 u 和 v 满足:要么 u 可以达 v,要么 v 可以达 u(u,v相互可达也行). ...

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

    给一个有向图G,求一个子图要求当中随意两点至少有一边可达. 问这个子图中最多含多少个顶点. 首先找SCC缩点建图.每一个点的权值就是该点包括点的个数. 要求当中随意两点可达,实际上全部边仅仅能同方向, ...

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

    题意:给定一个有向图,求一个最大的结点集,使得任意两个结点,要么 u 能到 v,要么 v 到u. 析:首先,如果是同一个连通分量,那么要么全选,要么全不选,然后我们就可以先把强连通分量先求出来,然后缩 ...

  7. BZOJ 1179 Atm(强连通分量缩点+DP)

    题目说可以通过一条边多次,且点权是非负的,所以如果走到图中的一个强连通分量,那么一定可以拿完这个强连通分量上的money. 所以缩点已经很明显了.缩完点之后图就是一个DAG,对于DAG可以用DP来求出 ...

  8. POJ3160 Father Christmas flymouse[强连通分量 缩点 DP]

    Father Christmas flymouse Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 3241   Accep ...

  9. UVa11324 The Largest Clique(强连通分量+缩点+记忆化搜索)

    题目给一张有向图G,要在其传递闭包T(G)上删除若干点,使得留下来的所有点具有单连通性,问最多能留下几个点. 其实这道题在T(G)上的连通性等同于在G上的连通性,所以考虑G就行了. 那么问题就简单了, ...

随机推荐

  1. jQuery对象数据缓存Cache原理及jQuery.data详解

    网上有很多教你怎么使用jQuery.data(..)来实现数据缓存,但有两个用户经常使用的data([key],[value])和jQuery.data(element,[key],[value])几 ...

  2. ZOJ 3824 Fiber-optic Network

    Fiber-optic Network Time Limit: 15000ms Memory Limit: 262144KB This problem will be judged on ZJU. O ...

  3. 内置函数--map,filter,reduce

    一.map class map(object): """ map(func, *iterables) --> map object Make an iterator ...

  4. FZU-1881-Problem 1881 三角形问题,打表二分查找~~

    B - 三角形问题 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Descripti ...

  5. 《计算机网络课程设计》基本操作(基于Cisco Packet Tracer)

    第一次课 Router> #用户模式 Router# #特权模式 lhx(config)# #全局配置模式 Router>enable #进入特权模式 Router#configure t ...

  6. .NET 调用java webservice保存datetime类型数据为空的解决办法

    问题描述:       用C#.NET调用Java开发的WebService时,先在客户端封装的带有int属性的对象,当将该对象传到服务器端时,服务器端可以得到 string类型的属性值,却不能得到i ...

  7. [Vijos] SuperBrother打鼹鼠

    背景 SuperBrother在机房里闲着没事干(再对比一下他的NOIP,真是讽刺啊......),于是便无聊地开始玩“打鼹鼠”...... 描述 在这个“打鼹鼠”的游戏中,鼹鼠会不时地从洞中钻出来, ...

  8. BZOJ1742: [Usaco2005 nov]Grazing on the Run 边跑边吃草

    数轴上n<=1000个点,从p出发以任意顺序走到所有的点,求到达每个点的时间之和的最小值. 好题!看起来水水的实际易错! 显然的结论是经过一个区间点之后肯定落在左端点或右端点上,谁没事最后还往中 ...

  9. msp430项目编程20

    msp430中项目---超声波测距系统 1.定时器工作原理 2.电路原理说明 3.代码(显示部分) 4.代码(功能实现) 5.项目总结 msp430项目编程 msp430入门学习

  10. codeforces #302Div1 A

    对于 我这样的弱者就需要一道一道 简单的题 来慢慢补了. 看懂 题意很重要: 又一次被自己的英语吓哭了,做了两天发现题目看错,结果样例都对了, 硬是过不了: 给 n,m,b,mod; 在给n 个数 a ...