UVA11324 The Largest Clique

题目描述

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

输入输出格式

输入格式:

第一行:测试数据组数\(T\),每组数据的格式如下:

第一行为结点数 \(n\) 和边数 \(m\) ,结点编号 \(1~n\)。

以下\(m\)行每行两个整数 \(u\) 和 \(v\) ,表示一条有向边 \(u->v\)。

输出格式:

每组数据输出最大结点集的结点数

输入输出样例

输入样例#1:

1
5 5
1 2
2 3
3 1
4 1
5 2

输出样例#1:

4

题解

首先,我们会想到\(Tarjan\)缩点,将缩成的点的\(siz\)大小当做点权。

因为缩完点之后就会是一个\(DAG\),所以可以跑DP。

这种题型有两种实现方式,\(topsort\)和记忆化搜索,代码中已注明。

转移就是\(dp[v]=max(dp[v],dp[u]+siz[v])\).

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<queue>
#define R register
#define ll long long
#define N 1005
#define M 50005
using namespace std;
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
a=f*x;
}
int T,n,m,u[M],v[M],ru[N],siz[N],h[N],sta[N],low[N],dfn[N];
int top,num,tot,col[M],vis[N],dp[N],ans,cnt;
struct node{
int nex,to;
}edge[M];
inline void add(R int u,R int v){
edge[++tot].nex=h[u];
edge[tot].to=v;
h[u]=tot;
}
inline void Tarjan(R int x){
dfn[x]=low[x]=++num;
sta[++top]=x;vis[x]=1;
for(R int i=h[x];i;i=edge[i].nex){
R int xx=edge[i].to;
if(!dfn[xx]){
Tarjan(xx);
low[x]=min(low[x],low[xx]);
}
else if(vis[xx])low[x]=min(low[x],dfn[xx]);
}
if(dfn[x]==low[x]){
R int now=-1;
cnt++;
while(now!=x){
now=sta[top];
top--;
col[now]=cnt;
siz[cnt]++;
vis[now]=0;
}
}
}
inline void init(){
tot=num=top=ans=cnt=0;
memset(h,0,sizeof(h));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(vis,0,sizeof(vis));
memset(siz,0,sizeof(siz));
memset(sta,0,sizeof(sta));
memset(col,0,sizeof(col));
memset(ru,0,sizeof(ru));
memset(dp,-1,sizeof(dp));
}
inline void topsort(){
queue<int> q;
while(!q.empty())q.pop();
for(R int i=1;i<=cnt;i++)
if(!ru[i])q.push(i),dp[i]=siz[i];
while(!q.empty()){
R int x=q.front();q.pop();
for(R int i=h[x];i;i=edge[i].nex){
R int xx=edge[i].to;
dp[xx]=max(dp[x]+siz[xx],dp[xx]);
--ru[xx];
if(!ru[xx])q.push(xx);
}
}
}
inline int search(R int x){
if(dp[x]!=-1)return dp[x];
R int res=siz[x];
for(R int i=h[x];i;i=edge[i].nex){
R int xx=edge[i].to;
res=max(search(xx)+siz[x],res);
}
return dp[x]=res;
}
int main(){
read(T);
while(T--){
read(n);read(m);init();
for(R int i=1;i<=m;i++)
read(u[i]),read(v[i]),add(u[i],v[i]);
for(R int i=1;i<=n;i++)
if(!dfn[i])Tarjan(i);
tot=0;memset(h,0,sizeof(h));
for(R int i=1;i<=m;i++)
if(col[u[i]]!=col[v[i]])
add(col[u[i]],col[v[i]]),ru[col[v[i]]]++;
//记忆化搜索
for(R int i=1;i<=cnt;i++)
ans=max(ans,search(i));
//拓扑排序
topsort();
for(R int i=1;i<=cnt;i++)
ans=max(ans,dp[i]);
printf("%d\n",ans);
}
return 0;
}

【UVA11324】 The Largest Clique (Tarjan+topsort/记忆化搜索)的更多相关文章

  1. luogu3953 [NOIp2017]逛公园 (tarjan+dijkstra+记忆化搜索)

    先跑一边dijkstra算出从1到i的最短距离dis[i] 然后建反向边 从n开始记忆化搜索,(p,k)表示1到p的距离=dis[p]+k的方案数 答案就是$\sum\limits_{i=0}^{k} ...

  2. 『题解』UVa11324 The Largest Clique

    原文地址 Problem Portal Portal1:UVa Portal2:Luogu Portal3:Vjudge Description Given a directed graph \(\t ...

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

    题目链接:https://vjudge.net/problem/UVA-11324 题解: 题意:给出一张有向图,求一个结点数最大的结点集,使得任意两个结点u.v,要么u能到达v, 要么v能到达u(u ...

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

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

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

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

  6. bzoj 1589: [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果【tarjan+记忆化搜索】

    对这个奇形怪状的图tarjan,然后重新连边把图变成DAG,然后记忆化搜索即可 #include<iostream> #include<cstdio> using namesp ...

  7. 洛谷 2921 记忆化搜索 tarjan 基环外向树

    洛谷 2921 记忆化搜索 tarjan 传送门 (https://www.luogu.org/problem/show?pid=2921) 做这题的经历有点玄学,,起因是某个random题的同学突然 ...

  8. ZOJ3795 Grouping(强连通分量+缩点+记忆化搜索)

    题目给一张有向图,要把点分组,问最少要几个组使得同组内的任意两点不连通. 首先考虑找出强连通分量缩点后形成DAG,强连通分量内的点肯定各自一组,两个强连通分量的拓扑序能确定的也得各自一组. 能在同一组 ...

  9. LightOJ1417 Forwarding Emails(强连通分量+缩点+记忆化搜索)

    题目大概是,每个人收到信息后会把信息发给他认识的一个人如此下去,问一开始要把信息发送给谁这样看到信息的人数最多. 首先找出图中的SCC并记录每个SCC里面的点数,如果传到一个SCC,那么里面的人都可以 ...

随机推荐

  1. mybaties 一对多关系映射

    背景: 数据库格式如下图所示 现在要统计出在一段时间内dimension_type为op即所有运营商的pv.uv.vv等指标的数组,以便页面显示出每个运营商在该事件段内历史指标曲线图. 分析: 返回的 ...

  2. dll函数生成规则

    [转]http://blog.csdn.net/beanjoy/article/details/9136127 所谓名字修饰约定,就是指变量名.函数名等经过编译后重新输出名称的规则. 比如源代码中函数 ...

  3. scala的隐式转换

    摘要: 通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码.   使用方式: 1. ...

  4. PHP发红包程序限制红包的大小

    我们先来分析下规律. 设定总金额为10元,有N个人随机领取: N=1 第一个 则红包金额=X元: N=2 第二个 为保证第二个红包可以正常发出,第一个红包金额=0.01至9.99之间的某个随机数. 第 ...

  5. 如何写摘要(abstract)

  6. VS2012用正则表达式统计行数

    使用正则表达式: b*[^:b#/]+.*$

  7. HDU 4714 Tree2cycle (树形DP)

    题意:给定一棵树,断开一条边或者接上一条边都要花费 1,问你花费最少把这棵树就成一个环. 析:树形DP,想一想,要想把一棵树变成一个环,那么就要把一些枝枝叶叶都换掉,对于一个分叉是大于等于2的我们一定 ...

  8. 编写高质量代码改善C#程序的157个建议——建议119:不要使用自己的加密算法

    建议119:不要使用自己的加密算法 很多人认为自己写的加密算法才是安全的,因为该算法只有“自己知道”.很遗憾,这是大错特错. 首先,我们不是秘密学专家,如果我们随随便便写个算法就称得上是加密算法的话, ...

  9. 练习题。对DOM中document的深刻理解巩固

    //window.onload = modTwo;     1.点击单元格内容  弹窗promrt接收值   将接受的值提换单元格内容    2.点击单元格  出现2个按钮 加粗 字体颜色标红     ...

  10. C#函数式程序设计之惰性列表工具——迭代器

    有效地处理数据时当今程序设计语言和框架的一个任务..NET拥有一个精心构建的集合类系统,它利用迭代器的功能实现对数据的顺序访问. 惰性枚举是一个迭代方法,其核心思想是只在需要的时候才去读取数据.这个思 ...