UVA11324 The Largest Clique 强连通分量缩点+有向无环图最大点权和
来源:互联网 发布:js调用servlet 编辑:程序博客网 时间:2024/05/16 18:37
题意:给一个有向图,求一个结点数最大的结点集,使得该结点集中任意两个结点u和v满足:要么u可以到达v,要么v可以到达u(u和v相互可达也可以)。
解法:可以发现的是,在同一个强连通分量里面的点要么都选,要么都不选。把强连通分量缩点重新建图后得到一个有向无环图,每个点代表一个强连通分量,新图的每个点有点权,点权为缩点后这个点的强连通分量有几个点。
然后问题就转化成在一个有向无环图中,每个点有点权,没有边权,求一条路径使得点权和最大。第一种:因为最多只有1000个点,所以枚举起点也是可行的。第二种:做法类似树形DP,在新图中,对于没访问过的点,寻找能从它子树中更新过来最大路径点权值加上自身点权,已经访问过的直接返回就是了。
CODE
#include <bits/stdc++.h>using namespace std;const int N = 1010;const int INF = 1e9;struct node{ int v,next; node(){} node(int v,int next): v(v),next(next){}}E[N*200];int n,m,top;int dfs_clock,scc_cnt; ///时间戳和强连通分量个数int dis[N]; ///重新建图后用来求图上最长的一条路径int head[N]; ///原图头结点int root[N]; ///新图头结点int scc_po[N]; ///新图缩点后每个联通分量有多少个点int dfn[N],low[N]; ///计算SCC用bool G[N][N]; ///重新建图的去重边int sccno[N]; ///标记每个点属于哪个强连通分量stack<int> S; ///Tarjan存点void Init() ///初始化{ dfs_clock = scc_cnt = top = 0; while(!S.empty()) S.pop(); for(int i = 0;i < N;i++){ head[i] = -1; root[i] = -1; dis[i] = scc_po[i] = dfn[i] = low[i] = sccno[i] = 0; for(int j = 0;j < N;j++) G[i][j] = false; }}void add(int u,int v) ///原图加边{ E[top] = node(v,head[u]); head[u] = top++;}void adde(int u,int v){ ///<span style="font-family: Arial, Helvetica, sans-serif;">新图加边</span> E[top] = node(v,root[u]); root[u] = top++;}void dfs(int u) { dfn[u] = low[u] = ++dfs_clock; S.push(u); for(int i = head[u];i != -1;i = E[i].next){ int v = E[i].v; if(!dfn[v]){ dfs(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++; while(1){ int x = S.top(); S.pop(); sccno[x] = scc_cnt; if(x == u) break; } }}void find_scc(int n) ///求强连通分量{ for(int i = 1;i <= n;i++){ if(!dfn[i]) dfs(i); }}int tree_D(int u) ///求新图的最长路径{ if(dis[u]) return dis[u]; dis[u] = scc_po[u]; int maxx = 0; for(int i = root[u];i != -1;i = E[i].next){ int v = E[i].v; int f = tree_D(v); maxx = max(maxx,f); } if(maxx) return dis[u] = dis[u]+maxx; else return 0;}int main(void){ int T; scanf("%d",&T); while(T--){ Init(); scanf("%d%d",&n,&m); for(int i = 1;i <= m;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v); } find_scc(n); for(int i = 1;i <= n;i++){ ///重新建图 for(int j = head[i];j != -1;j = E[j].next){ int v = E[j].v; if(sccno[i] == sccno[v]) continue; if(G[sccno[i]][sccno[v]]) continue; adde(sccno[i],sccno[v]); G[sccno[i]][sccno[v]] = true; } } for(int i = 1;i <= n;i++){ ///对重新建图后每个联通有多少个点进行计数 scc_po[sccno[i]]++; } for(int i = 1;i <= n;i++){ ///求出新图中的最长路径 if(!dis[i]) tree_D(i); } int ans = 0; for(int i = 1;i <= n;i++) ans = max(ans,dis[i]); printf("%d\n",ans); } return 0;}
0 0
- UVA11324 The Largest Clique 强连通分量缩点+有向无环图最大点权和
- uva11324 - The Largest Clique 有向图强连通分量+缩点+DP
- UVA 11324 - The Largest Clique(强连通分量+缩点)
- UVa11324 The Largest Clique(强连通分量+DP)
- UVA 11324 The Largest Clique(tarjan有向图强连通+缩点)
- UVA 11324 The Largest Clique(tarjan有向图强连通+缩点)
- uva11324 The Largest Clique --- 强连通+dp
- uva 11324 The Largest Clique(强连通分量缩点+DAG动态规划)
- UVA 11324 The Largest Clique (强连通分量+缩点+dp)
- UVA 11324 The Largest Clique(强连通分量+缩点DAG的DP)
- Uva-11324 The Largest Clique(强连通分量缩点+DAGdp)
- UVA11324 The Largest Clique (强联通+缩点+DAG上DP最长路)
- Uva--11324--The Largest Clique【有向图强连通分量】
- 【UVa11324】最大团The Largest Clique【强联通分量】【DAG】
- UVA11324 - The Largest Clique(强连通最大团)
- poj2676 有向图强连通分量+缩点
- UVA11324 The Largest Clique (强联通 + DP)
- UVa 11324 The Largest Clique / 强连通分量
- 工具类:异步加载AsyncTask和用法
- Spring In Action学习笔记:Bean的简单装配
- GPL协议 与 LGPL协议
- java项目管理工具——maven
- 【积分】【概率】Probability, UVa11346
- UVA11324 The Largest Clique 强连通分量缩点+有向无环图最大点权和
- HDU 5573 Binary Tree(2015-ICPC-上海赛区)
- c宏定义
- VC中画基准线,随鼠标移动
- 三子棋C语言实现(多种模式任你选)
- 打印两种菱形。
- 探秘腾讯新总部:互联网巨头是这样玩黑科技的
- poj 3624 Charm Bracelet (0-1)
- cocos2djs学习笔记-ccui.ScrollView