zoukankan      html  css  js  c++  java
  • HDU 3639 HawkandChicken(强连通分量)

     

    题目大意

     

    有 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 人数最多的点,输出组成这些点的人即可

     

    参考代码

    HDU 3639
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <stack>
      6 #include <vector>
      7 
      8 using namespace std;
      9 
     10 const int N=5006;
     11 
     12 stack <int> s;
     13 vector <int> adj[N], arc[N], com[N], ans;
     14 int n, m, t, ind, T, sum;
     15 int dfn[N], low[N], id[N], in[N];
     16 bool vs[N];
     17 
     18 void tarjan(int u)
     19 {
     20     dfn[u]=low[u]=T++;
     21     s.push(u), vs[u]=1;
     22     int len=(int)adj[u].size();
     23     for(int i=0; i<len; i++)
     24     {
     25         int v=adj[u][i];
     26         if(dfn[v]==-1)
     27         {
     28             tarjan(v);
     29             if(low[u]>low[v]) low[u]=low[v];
     30         }
     31         else if(vs[v] && low[u]>dfn[v]) low[u]=dfn[v];
     32     }
     33     if(low[u]==dfn[u])
     34     {
     35         for(int v; 1; )
     36         {
     37             v=s.top();
     38             s.pop(), vs[v]=0;
     39             id[v]=ind, com[ind].push_back(v);
     40             if(v==u) break;
     41         }
     42         ind++;
     43     }
     44 }
     45 
     46 void DFS(int u)
     47 {
     48     vs[u]=1;
     49     int len=(int)arc[u].size();
     50     sum+=(int)com[u].size(); // 可以优化
     51     for(int i=0; i<len; i++)
     52     {
     53         int v=arc[u][i];
     54         if(vs[v]) continue;
     55         DFS(v);
     56     }
     57 }
     58 
     59 int main()
     60 {
     61     scanf("%d", &t);
     62     for(int ca=1; ca<=t; ca++)
     63     {
     64         scanf("%d%d", &n, &m);
     65         for(int i=0; i<n; i++) adj[i].clear();
     66         for(int i=0, a, b; i<m; i++)
     67         {
     68             scanf("%d%d", &a, &b);
     69             adj[a].push_back(b);
     70         }
     71         for(int i=0; i<n; i++) vs[i]=0, dfn[i]=-1, com[i].clear();
     72         ind=T=0;
     73         while(!s.empty()) s.pop();
     74         for(int i=0; i<n; i++) if(dfn[i]==-1) tarjan(i);
     75         for(int i=0; i<ind; i++) arc[i].clear(), in[i]=0, dfn[i]=0;
     76         for(int i=0; i<n; i++)
     77         {
     78             int len=(int)adj[i].size();
     79             for(int j=0; j<len; j++)
     80             {
     81                 int v=id[adj[i][j]];
     82                 int u=id[i];
     83                 if(u!=v) arc[v].push_back(u), in[u]++;
     84             }
     85         }
     86         for(int i=0; i<ind; i++)
     87         {
     88             if(in[i]!=0) continue;
     89             for(int j=0; j<ind; j++) vs[j]=0;
     90             sum=0;
     91             DFS(i);
     92             dfn[i]=sum;
     93         }
     94         int Max=-0x3fffffff;
     95         for(int i=0; i<ind; i++)
     96             if(Max<dfn[i]) Max=dfn[i];
     97         ans.clear();
     98         for(int i=0; i<ind; i++)
     99         {
    100             if(dfn[i]!=Max) continue;
    101             int len=(int)com[i].size();
    102             for(int j=0; j<len; j++) ans.push_back(com[i][j]);
    103         }
    104         sort(ans.begin(), ans.end());
    105         int len=(int)ans.size();
    106         printf("Case %d: %d\n", ca, Max-1);
    107         for(int i=0; i<len; i++)
    108         {
    109             printf("%d", ans[i]);
    110             if(i==len-1) printf("\n");
    111             else printf(" ");
    112         }
    113 
    114     }
    115     return 0;
    116 }

     

    AC通道

    HDU 3639 Hawk-and-Chicken

  • 相关阅读:
    c# 读取数据库得到dateset
    c# 读数据库二进制流到图片
    c# 读取数据库得到字符串
    c#打开颜色对话框
    WinForm-GridView
    arcengine 常用方法
    arcgis engine 调用arcgis server服务
    ae
    ae保存图层
    ae 打开地图文档
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/2962296.html
Copyright © 2011-2022 走看看