题目地址:
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 ",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(" "); 157 } 158 //clock_t ed=clock(); 159 //printf(" Time Used : %.5lf Ms. ",(double)(ed-st)/CLOCKS_PER_SEC); 160 return 0; 161 }