HDOJ3639解题报告【缩点+dfs】

题目地址:

  http://acm.hdu.edu.cn/showproblem.php?pid=3639

题目概述:

  题面有点翻译不来……可以用Chrome自带的那个翻译。

大致思路:

  如果跑bfs或者dfs遇到环的话就会出问题,所以先跑一遍tarjan求强连通分量,把环的情况去掉,在剩下的图上做。

  这个时候发现样例1里2这个节点指向的两个节点都是答案,所以反向建图,用dfs求出所有入度为0的点的子树大小,最大数即为答案。

  输出节点的时候直接对0~n-1循环找即可。

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <vector>
  6 #include <ctime>
  7 #include <map>
  8 #include <stack>
  9 #include <queue>
 10 #include <cstring>
 11 #include <algorithm>
 12 using namespace std;
 13 
 14 #define sacnf scanf
 15 #define scnaf scanf
 16 #define maxn  5010
 17 #define maxm 26
 18 #define inf 1061109567
 19 #define Eps 0.00001
 20 const double PI=acos(-1.0);
 21 #define mod 7
 22 #define MAXNUM 10000
 23 void Swap(int &a,int &b) {int t=a;a=b;b=t;}
 24 int Abs(int x) {return (x<0)?-x:x;}
 25 typedef long long ll;
 26 typedef unsigned int uint;
 27 
 28 vector<int> G[maxn];
 29 vector<int> rG[maxn];
 30 stack<int> S;
 31 
 32 struct node
 33 {
 34     int pos,val;
 35     bool operator < (const node &a) const
 36     {
 37         return val<a.val;
 38     }
 39 };
 40 
 41 int pre[maxn],low[maxn],scc[maxn],scc_val[maxn];
 42 int scc_cnt,dfs_clock;
 43 int n,m;
 44 int ans[maxn],in[maxn],cnt[maxn],vis[maxn];
 45 
 46 void dfs(int u)
 47 {
 48     pre[u]=low[u]=++dfs_clock;
 49     int len=G[u].size();S.push(u);
 50     for(int i=0;i<len;i++)
 51     {
 52         int v=G[u][i];
 53         if(!pre[v])
 54         {
 55             dfs(v);
 56             low[u]=min(low[u],low[v]);
 57         }
 58         else if(!scc[v]) low[u]=min(low[u],pre[v]);
 59     }
 60     if(pre[u]==low[u])
 61     {
 62         scc_cnt++;int cnt=0;
 63         for(;;)
 64         {
 65             int t=S.top();S.pop();
 66             scc[t]=scc_cnt;cnt++;
 67             if(t==u) break;
 68         }
 69         scc_val[scc_cnt]=cnt;
 70     }
 71 }
 72 
 73 void find_scc()
 74 {
 75     memset(pre,0,sizeof(pre));
 76     memset(low,0,sizeof(low));
 77     memset(scc,0,sizeof(scc));
 78     scc_cnt=0;dfs_clock=0;
 79     for(int i=1;i<=n;i++)
 80     {
 81         if(!pre[i]) dfs(i);
 82     }
 83 }
 84 
 85 int Count(int u)
 86 {
 87     vis[u]=1;
 88     int len=rG[u].size(),sum=scc_val[u];
 89     for(int i=0;i<len;i++)
 90     {
 91         int v=rG[u][i];
 92         if(!vis[v]) sum+=Count(v);
 93     }
 94     return sum;
 95 }
 96 
 97 int main()
 98 {
 99     //freopen("data.in","r",stdin);
100     //freopen("data.out","w",stdout);
101     //clock_t st=clock();
102     int T;scanf("%d",&T);
103     for(int kase=1;kase<=T;kase++)
104     {
105         int a,b;scanf("%d%d",&n,&m);
106         for(int i=1;i<=n;i++)
107         {
108             G[i].clear();
109         }
110         for(int i=1;i<=m;i++)
111         {
112             scanf("%d%d",&a,&b);
113             a++;b++;G[a].push_back(b);
114         }
115         find_scc();
116 
117         ///缩点
118         for(int i=1;i<=scc_cnt;i++)
119         {
120             in[i]=0;cnt[i]=-1;
121             rG[i].clear();
122         }
123         for(int i=1;i<=n;i++)
124         {
125             for(int j=1;j<=scc_cnt;j++) vis[j]=0;
126             int len=G[i].size();
127             for(int k=0;k<len;k++)
128             {
129                 int j=G[i][k];
130                 if(scc[i]!=scc[j]&&!vis[scc[j]])
131                 {
132                     vis[scc[j]]=1;rG[scc[j]].push_back(scc[i]);
133                     in[scc[i]]++;
134                 }
135             }
136         }
137 
138         int ans=-1;bool flag=false;
139         for(int i=1;i<=scc_cnt;i++)
140         {
141             if(!in[i])
142             {
143                 for(int j=1;j<=scc_cnt;j++) vis[j]=0;
144                 cnt[i]=Count(i);ans=max(ans,cnt[i]);
145             }
146         }
147         printf("Case %d: %d\n",kase,ans-1);
148         for(int i=1;i<=n;i++)
149         {
150             if(ans==cnt[scc[i]])
151             {
152                 if(flag) printf(" ");
153                 printf("%d",i-1);flag=true;
154             }
155         }
156         printf("\n");
157     }
158     //clock_t ed=clock();
159     //printf("\n\nTime Used : %.5lf Ms.\n",(double)(ed-st)/CLOCKS_PER_SEC);
160     return 0;
161 }

 

posted @ 2017-03-24 10:37  CtrlKismet  阅读(233)  评论(0编辑  收藏  举报