HDU 3639 Hawk-and-Chicken 强联通缩点 + DFS
来源:互联网 发布:剑侠情缘手游工资算法 编辑:程序博客网 时间:2024/05/17 17:42
题意:n个小朋友传递手帕,如果A传递给B B传递给C 那么C会得到A和B的手帕,问你那些小朋友会得到最多种类的手帕(不算自己的手帕)。
思路:对于在同一个强联通分量的小朋友,他们得到的手帕数量是相同的,都为所在联通分量点数减一,我们将其缩点,得到一个DAG,剩下的就是计算出度为零的小朋友会得到多少种手帕,正着找不好找,我们将所有边反向,从终点找所有能遍历到的点,更新最大值即可。
#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>using namespace std;#define REP( i, a, b ) for( int i = a; i < b; i++ )#define CLR( a , x ) memset( a , x , sizeof a )const int maxn = 5000 + 10;const int maxe = 100000 + 10;struct Edge{ int v, next; Edge (int v = 0, int next = 0) : v(v), next(next) {}};struct SCC{ int Head[maxn], cntE; int dfn[maxn], low[maxn], dfs_clock; int scc[maxn], scc_cnt; int Stack[maxn], top; bool ins[maxn]; Edge edge[maxe]; void init(){ top = 0; cntE = 0; scc_cnt = 0; dfs_clock = 0; CLR(ins, 0); CLR(dfn, 0); CLR(Head, -1); } void add(int u, int v){ edge[cntE] = Edge(v, Head[u]); Head[u] = cntE++; } void Tarjan(int u){ dfn[u] = low[u] = ++dfs_clock; Stack[top++] = u; ins[u] = 1; for (int i = Head[u] ; ~i ; i = edge[i].next){ int v = edge[i].v; if (!dfn[v]){ Tarjan (v) ; low[u] = min(low[u], low[v]) ; } else if (ins[v]) low[u] = min (low[u], dfn[v]) ; } if (low[u] == dfn[u]){ ++scc_cnt; while ( 1 ){ int v = Stack[--top]; ins[v] = 0; scc[v] = scc_cnt; if (v == u) break; } } } void find_scc(int n){ REP(i, 0, n) if(!dfn[i]) Tarjan (i) ; }}scc;Edge e[maxe];int cnte, H[maxn];int cost[maxn], in[maxn];int ANS[maxn];int cur_cost[maxn];int vis[maxn];int n, m;vector<int> ans_scc;void Init(){ memset(H, -1, sizeof(H)); memset(cost , 0, sizeof(cost)); memset(ANS, 0, sizeof(ANS)); memset(in, 0, sizeof(in)); cnte = 0; ans_scc.clear();}void Add(int u, int v){ e[cnte] = Edge(v, H[u]); H[u] = cnte++;}int cur_sum;void dfs(int u){ for(int i = H[u]; ~i; i = e[i].next){ int v = e[i].v; if(!vis[v]){ vis[v] = 1; cur_sum += cost[v]; dfs(v); } }}int cas = 0;void solve(){ scanf("%d%d", &n, &m); scc.init(); for(int i = 0; i < m; i++){ int u, v; scanf("%d%d", &u, &v); scc.add(u, v); } scc.find_scc(n); Init(); for(int i = 0; i < n; i++) for(int j = scc.Head[i]; ~j; j = scc.edge[j].next){ int u = i, v = scc.edge[j].v; if(scc.scc[u] != scc.scc[v]){ Add(scc.scc[v], scc.scc[u]); in[scc.scc[u]]++; } } for(int i = 0; i < n; i++) cost[scc.scc[i]]++; int ans = 0; for(int i = 1; i <= scc.scc_cnt; i++) if(!in[i]){ cur_sum = cost[i]; memset(vis, 0, sizeof(vis)); dfs(i); ANS[i] = cur_sum; ans = max(ans, cur_sum); } int f = 0; printf("Case %d: %d\n", ++cas, ans - 1); for(int i = 0; i < n; i++){ if(ANS[scc.scc[i]] == ans){ if(f) printf(" "); f = 1; printf("%d", i); } } printf("\n");}int main(){ //freopen("in.txt", "r", stdin); int T; scanf("%d", &T); while(T--) solve(); return 0;}
0 0
- HDU 3639 Hawk-and-Chicken 强联通缩点 + DFS
- hdu 3639 Hawk-and-Chicken【强联通Tarjan+Dfs】
- 【HDU】3639 Hawk-and-Chicken 强连通缩点+DFS
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
- HDU 3639 Hawk-and-Chicken(Tarjan缩点+反向DFS)
- HDU 3639 Hawk-and-Chicken tarjan缩点+dfs
- HDU - 3639 Hawk-and-Chicken(dfs+强连通分量)
- HDU 3639Hawk-and-Chicken 强连通分量分解 + dfs
- Hawk-and-Chicken (hdu 3639 强连通缩点+反向建图DFS)
- HDU 3639 Hawk-and-Chicken 强连通缩点+搜索
- hdu 3639 Hawk-and-Chicken(缩点+树dp)
- hdu 3639 Hawk-and-Chicken 【强连通分量+反向建图dfs】
- HDU 3639 Hawk-and-Chicken(强连通)
- hdu 3639 Hawk-and-Chicken 强连通分量 targin
- [HDU3639]Hawk-and-Chicken(Tarjan缩点+dfs)
- HDU3639 Hawk-and-Chicken Tarjan缩点 +dfs+贪心
- java程序的参数传递分析
- 1754 HDU
- 二叉树-递归遍历(先、中、后)
- Fragment 碎片 (下)
- Android-多媒体编程
- HDU 3639 Hawk-and-Chicken 强联通缩点 + DFS
- 二叉树-非递归遍历(先、中、后)
- 操作字节数组
- 关于youku嵌入式播放器浏览器白色边框的问题
- 软件测试的风险主要体现在哪里?
- 如何用Python实现任一个英文的纯文本文件,统计其中的单词出现的个数?
- ORACLE命名规范
- 二叉树-层序遍历
- 关于BIOS的入口地址0xFFFF0