HDU 3639 Hawk-and-Chicken(强连通缩点+反向建图)
2017-05-06 17:04
465 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3639
题意:
有一群孩子正在玩老鹰抓小鸡,由于想当老鹰的人不少,孩子们通过投票的方式产生,但是投票有这么一条规则:投票具有传递性,A支持B,B支持C,那么C获得2票(A.B共两票),输出最多能获得的票数是多少张和获得最多票数的人是谁?
思路:
先强连通缩点反向建图,在计算强连通的时候,需要保存每个连通分支的结点个数。
为什么要反向建图呢?因为要寻找票数最多的,那么肯定是入度为0的点,然后dfs计算它的子节点的权值(连通分支结点个数)加起来有多少。
注意,最后要减去1,不能把自己也算进去。
题意:
有一群孩子正在玩老鹰抓小鸡,由于想当老鹰的人不少,孩子们通过投票的方式产生,但是投票有这么一条规则:投票具有传递性,A支持B,B支持C,那么C获得2票(A.B共两票),输出最多能获得的票数是多少张和获得最多票数的人是谁?
思路:
先强连通缩点反向建图,在计算强连通的时候,需要保存每个连通分支的结点个数。
为什么要反向建图呢?因为要寻找票数最多的,那么肯定是入度为0的点,然后dfs计算它的子节点的权值(连通分支结点个数)加起来有多少。
注意,最后要减去1,不能把自己也算进去。
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<cmath> #include<stack> using namespace std; const int maxn=5000+5; int n,m; int sum; vector<int> G[maxn]; int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt; int num[maxn]; //记录每个连通分支的结点个数 stack<int> S; vector<int> rG[maxn]; int in[maxn]; int vis[maxn]; int cnt[maxn]; void dfs(int u) { pre[u] = lowlink[u] = ++dfs_clock; S.push(u); for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (!pre[v]) { dfs(v); lowlink[u] = min(lowlink[u], lowlink[v]); } else if(!sccno[v]) lowlink[u] = min(lowlink[u], pre[v]); } if (pre[u] == lowlink[u]) { scc_cnt++; num[scc_cnt]=0; for(;;) { int x = S.top(); S.pop(); sccno[x] = scc_cnt; num[scc_cnt]++; if (x == u) break; } } } void find_scc(int n) { dfs_clock = scc_cnt = 0; memset(pre, 0, sizeof(pre)); memset(sccno, 0, sizeof(sccno)); for (int i = 0; i < n; i++) if (!pre[i]) dfs(i); } void dfs2(int u) { vis[u]=1; sum+=num[u]; for(int i=0;i<rG[u].size();i++) { int v=rG[u][i]; if(!vis[v]) dfs2(v); } } int main() { //freopen("D:\\input.txt","r",stdin); int T; int kase=0; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) G[i].clear(); while(m--) { int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); } find_scc(n); for(int i=1;i<=scc_cnt;i++) rG[i].clear(); memset(in,0,sizeof(in)); for(int u=0;u<n;u++) { for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(sccno[u]!=sccno[v]) {rG[sccno[v]].push_back(sccno[u]);in[sccno[u]]++;} } } int ans=0; memset(cnt,0,sizeof(cnt)); for(int i=1;i<=scc_cnt;i++) { sum=0; if(in[i]==0) //入度为0 { memset(vis,0,sizeof(vis)); dfs2(i); cnt[i]=sum-1; //需要减1,因为它自己所处的连通分支得把自己减去 ans=max(sum-1,ans); } } printf("Case %d: %d\n",++kase,ans); bool flag=true; for(int i=0;i<n;i++) { if(cnt[sccno[i]]==ans) { if(flag) {printf("%d",i);flag=false;} else printf(" %d",i); } } printf("\n"); } return 0; }
相关文章推荐
- HDU 3639 Hawk-and-Chicken(Tarjan缩点+反向DFS)
- HDU 3639 Hawk-and-Chicken(Tarjan缩点+反向DFS)
- hdu 3639 Hawk-and-Chicken (强连通 + 反图 + 缩点) && hdu1827 Summer Holiday && hdu 1269 迷宫城堡 && hdu3072 Intelligence System
- hdu 3639 Hawk-and-Chicken 【强连通分量+反向建图dfs】
- Hawk-and-Chicken (hdu 3639 强连通缩点+反向建图DFS)
- hdoj 3639 Hawk-and-Chicken 【有向图SCC】【缩点后反向建图 求最大传递值】
- HPU 3639--Hawk-and-Chicken【SCC缩点反向建图 && 求传递的最大值】
- HDU 3639 Hawk-and-Chicken(强连通)
- HPU 3639--Hawk-and-Chicken【SCC缩点反向建图 && 求传递的最大值】
- HDU 3639 Hawk-and-Chicken 强联通缩点 + DFS
- hdu 3639 Hawk-and-Chicken【强联通Tarjan+Dfs】
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
- hdu 3639 Hawk-and-Chicken 强连通分量 targin
- HDU 3639 Hawk-and-Chicken 强连通缩点+搜索
- 【HDU】3639 Hawk-and-Chicken 强连通缩点+DFS
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
- HDU 3639 SCC Hawk-and-Chicken
- HDU 3639 Hawk-and-Chicken
- hdu 3639 Hawk-and-Chicken 强连通分支
- HDU 3639 Hawk-and-Chicken