hdu 3639(强连通分量+dfs)
来源:互联网 发布:日本演员关口知宏 编辑:程序博客网 时间:2024/05/16 12:02
题目大意
有 n(2<=n<=5000) 个人,m(0<m<=30000) 个 support 关系(A support B)。问:哪些人得到的 support 最多。
需要注意的是 support 是可以传递的,比如:A support B && B support C,那么,C 得到的 support 是 2
做法分析
可以想到的是,枚举每个人得到的 support 的个数,这个做法是 o(n^2) 的。在 50 组数据的情况下,想要在 2s 内出结果,有点不现实
思来想去,这道题貌似没有什么好的做法
那么就想想怎么尽可能多的“剪枝”吧
首先,如果一堆人中,每两个人都可以相互支持(间接或者直接),那么这一堆人可以缩成一个“人”。
缩点之后,我们再反向建图,那么,能够得到最多的 support 的那一堆人,一定是图中入度为 0 的点
对建好的图中那些入度为 0 的点,DFS 遍历一遍,得到 support 这个点的人数
找到 support 人数最多的点,输出组成这些点的人即可
#include <cstdio>#include <algorithm>#include <cstring>#include <iostream>#include <stack>#include <vector>using namespace std;const int N=5006;stack <int> s;vector <int> adj[N], arc[N], com[N], ans;int n, m, t, ind, T, sum;int dfn[N], low[N], id[N], in[N];bool vs[N];void tarjan(int u){ dfn[u]=low[u]=T++; s.push(u), vs[u]=1; int len=(int)adj[u].size(); for(int i=0; i<len; i++) { int v=adj[u][i]; if(dfn[v]==-1) { tarjan(v); if(low[u]>low[v]) low[u]=low[v]; } else if(vs[v] && low[u]>dfn[v]) low[u]=dfn[v]; } if(low[u]==dfn[u]) { for(int v; 1; ) { v=s.top(); s.pop(), vs[v]=0; id[v]=ind, com[ind].push_back(v); if(v==u) break; } ind++; }}void DFS(int u){ vs[u]=1; int len=(int)arc[u].size(); sum+=(int)com[u].size(); // 可以优化 for(int i=0; i<len; i++) { int v=arc[u][i]; if(vs[v]) continue; DFS(v); }}int main(){ scanf("%d", &t); for(int ca=1; ca<=t; ca++) { scanf("%d%d", &n, &m); for(int i=0; i<n; i++) adj[i].clear(); for(int i=0, a, b; i<m; i++) { scanf("%d%d", &a, &b); adj[a].push_back(b); } for(int i=0; i<n; i++) vs[i]=0, dfn[i]=-1, com[i].clear(); ind=T=0; while(!s.empty()) s.pop(); for(int i=0; i<n; i++) if(dfn[i]==-1) tarjan(i); for(int i=0; i<ind; i++) arc[i].clear(), in[i]=0, dfn[i]=0; for(int i=0; i<n; i++) { int len=(int)adj[i].size(); for(int j=0; j<len; j++) { int v=id[adj[i][j]]; int u=id[i]; if(u!=v) arc[v].push_back(u), in[u]++; } } for(int i=0; i<ind; i++) { if(in[i]!=0) continue; for(int j=0; j<ind; j++) vs[j]=0; sum=0; DFS(i); dfn[i]=sum; } int Max=-0x3fffffff; for(int i=0; i<ind; i++) if(Max<dfn[i]) Max=dfn[i]; ans.clear(); for(int i=0; i<ind; i++) { if(dfn[i]!=Max) continue; int len=(int)com[i].size(); for(int j=0; j<len; j++) ans.push_back(com[i][j]); } sort(ans.begin(), ans.end()); int len=(int)ans.size(); printf("Case %d: %d\n", ca, Max-1); for(int i=0; i<len; i++) { printf("%d", ans[i]); if(i==len-1) printf("\n"); else printf(" "); } } return 0;}
0 0
- hdu 3639(强连通分量+dfs)
- HDU - 3639 Hawk-and-Chicken(dfs+强连通分量)
- HDU 3639Hawk-and-Chicken 强连通分量分解 + dfs
- hdu 5222(Tarjan求强连通分量+dfs)
- hdu 3639 Hawk-and-Chicken 【强连通分量+反向建图dfs】
- hdu 3072(强连通分量)
- hdu 2767(强连通分量)
- hdu 1269 强连通分量
- HDU 1827 强连通分量
- HDU 1269 强连通分量
- hdu-4612-强连通分量
- HDU 2767 强连通分量
- hdu 2767强连通分量
- HDU 1236 强连通分量
- hdu 1827强连通分量
- HDU 5934 强连通分量
- HDU 5934 强连通分量
- 双DFS求强连通分量
- coursera课程批量下载
- 着重介绍了非递归算法,特别是非递归后续遍历
- cocos2dx 常见的22种动画特效
- iOS 数据库详解 sqlite实现增删改查操作
- LAMP环境搭建
- hdu 3639(强连通分量+dfs)
- lua 类, 继承, 面向对象
- 我在南邮的三年—研二生活
- js ajax 兼容多浏览器 get post 解决乱码 响应过程全齐了
- OC 字典
- 一个小码农这半年的经验和教训
- kernel---x86中计算struct thread——info偏移地址
- android广播机制
- LRUCache初步实现