HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
来源:互联网 发布:浙江网络诈骗立案标准 编辑:程序博客网 时间:2024/06/06 04:25
题意:给你一个有向图,如果从u点能到达v点,那么说u是v的粉丝,现在要你按序输出那些粉丝数目最多的点编号.
思路:转自网上,写得很详细了
假设该图是一个强连通图,那么任一点都有n-1个粉丝(即n-1个点能到达它).所以我们把该图缩点变成一个新的DAG图.
结论:原图中具有最多粉丝的点一定在新图的那些出度为0的点所代表的分量中.
证明:假设u节点粉丝最多且它所属的分量出度不为0,那么u节点一定是某个节点v的粉丝,所以v的粉丝必然包含了u的所有粉丝加上u本身.所以v的粉丝必然多余u.由此矛盾.
下面的问题是如何找新DAG图的每个节点(所代表分量中的原节点)的最大粉丝数? 该粉丝数=本连通分量的点数-1+本连通分量能通过ß这种边逆向走到的所有分量的点数和. 所以我们直接建立缩点树的逆图DAG即可,如果u->v表示u分量将获得v分量的所有节点作为粉丝.所以我们只需要对那几个入度为0的点做DFS即可.
每次DFS到一个新节点,该点所代表的分量节点数就都加到sum上去,表示新加了很多粉丝.最后找最大粉丝值的分量点输出即可.
#include <cstdio>#include <queue>#include <cstring>#include <iostream>#include <cstdlib>#include <algorithm>#include <vector>#include <map>#include <string>#include <set>#include <ctime>#include <cmath>#include <cctype>#include <stack>using namespace std;#define maxn 100000+100#define LL long longint cas=1,T;vector<int>G[maxn],NewG[maxn];int pre[maxn];int lowlink[maxn];int sccno[maxn];int num[maxn]; //在i编号scc中有多少个点int dfs_clock,scc_cnt;int n,m;int fan[maxn]; //新的图中每个点的粉丝数stack<int>S;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 (lowlink[u] == pre[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(sccno,0,sizeof(sccno));memset(pre,0,sizeof(pre));for (int i = 0;i<n;i++)if (!pre[i])dfs(i);}int in[maxn];int out[maxn];bool vis[maxn];int dfs2(int u){vis[u]=1;int sum = 0;for (int i = 0;i<NewG[u].size();i++){int v = NewG[u][i];if (!vis[v])sum+=num[v]+dfs2(v);}return sum;}int main(){//freopen("in","r",stdin);scanf("%d",&T);while (T--){//printf("Case %d: ",cas++);scanf("%d%d",&n,&m);for (int i = 0;i<=n;i++)G[i].clear();memset(out,0,sizeof(out));memset(in,0,sizeof(in));memset(num,0,sizeof(num));for (int i = 1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);G[u].push_back(v);}find_scc(n);for (int i = 0;i<=scc_cnt;i++){ out[i]=0;in[i]=0;NewG[i].clear();}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]){ NewG[sccno[v]].push_back(sccno[u]);in[sccno[u]]++;}}memset(fan,0,sizeof(fan));int maxf=-1;for (int i = 1;i<=scc_cnt;i++){if (!in[i]){memset(vis,0,sizeof(vis));fan[i]=num[i]-1+dfs2(i);maxf=max(fan[i],maxf);}}bool win[maxn];memset(win,0,sizeof(win));for (int i = 0;i<n;i++)if (fan[sccno[i]]==maxf)win[i]=1;printf("Case %d: %d\n",cas++,maxf);bool first = 1;for (int i = 0;i<n;i++)if (win[i]){if (first)printf("%d",i),first=0;elseprintf(" %d",i);} puts("");}return 0;}
0 0
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
- hdu 3639 Hawk-and-Chicken 强连通分量 targin
- HDU - 3639 Hawk-and-Chicken(dfs+强连通分量)
- HDU 3639Hawk-and-Chicken 强连通分量分解 + dfs
- 【强连通分量】 HDOJ 3639 Hawk-and-Chicken
- HDOJ 3639.Hawk-and-Chicken(Tarjan强连通分量+缩点)
- HDU 3639 Hawk-and-Chicken 强联通缩点 + DFS
- HDU 3639 Hawk-and-Chicken (强连通分量+树形DP)
- hdu 3639 Hawk-and-Chicken 【强连通分量+反向建图dfs】
- HDU 3639 Hawk-and-Chicken(强连通)
- 【HDU】3639 Hawk-and-Chicken 强连通缩点+DFS
- HDU 3639 Hawk-and-Chicken 强连通缩点+搜索
- HDU3639--Hawk-and-Chicken(强连通+缩点+反向图)
- HDU3639 Hawk-and-Chicken 强连通+缩点+建反向图
- hdu 3639 Hawk-and-Chicken(缩点+树dp)
- HDU 3639 Hawk-and-Chicken(Tarjan缩点+反向DFS)
- hdu2824 2010.2.26
- L2 正则化
- poj2926 2010.2.26
- Java设计模式(十八)----命令模式
- hdu3220 2010.3.1
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
- XStream的使用(2)——集合形式的 JavaBean 转化为 xml
- HYSBZ/BZOJ 1037 [ZJOI2008] 生日聚会Party - dp
- Etaoin Shrdlu 2010.3.2
- frm.Show();Application.Run
- Android开发笔记(五十七)录像录音与播放
- hdu2822 2010.3.2
- Gradle(1)——基本概念与Android Studio Gradle结构
- Activity之间数据交流(onActivityResult的用法)