题意:有 n 个人,m 组支持关系,已知支持关系可以传递,比如 A 支持 B,则所有支持 A 的人也同时支持 B,问哪些人获得的支持数最多,最多获得多少支持(自己不能获得自己的支持)。
首先,如果一些人他们互相支持,那么他们的支持数肯定都是一样的,所有支持他们其中一个人的也同时支持他们所有人,所以对于这些人我们可以强连通缩点。然后就获得了一个有向无环图,每个强连通分量有各自的人数。由于支持的人数可以传递,所以某个人支持了别人,那么他获得的支持数就一定不如他支持的人多,那么其实我们需要获得的就只是那些没有支持过别人的人,所以我们可以通过反向建图,那些没有支持别人的人就是入度为 0 的点,从每个这样的点开始DFS下去统计一共有多少个人是他能够到达的,然后再加上他自己的人数 - 1(不能获得自己的支持),这样我们再从中找出最大值以及这些人就行了。
1 #include2 #include 3 #include 4 #include 5 using namespace std; 6 7 const int maxn=5005; 8 const int maxm=30005; 9 10 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2]; 11 int n,t,scccnt,maxx; 12 int stx[maxn],low[maxn],scc[maxn]; 13 int dp[maxn],id[maxn],vis[maxn]; 14 stack S; 15 16 int max(int a,int b){ return a>b?a:b;} 17 18 void init(){ 19 memset(head,-1,sizeof(head)); 20 size[0]=size[1]=0; 21 memset(dp,0,sizeof(dp)); 22 memset(id,0,sizeof(id)); 23 maxx=0; 24 } 25 26 void add(int a,int b,int c=0){ 27 if(c){ 28 for(int i=head[1][a];~i;i=nxt[1][i])if(point[1][i]==b)return; 29 } 30 point[c][size[c]]=b; 31 nxt[c][size[c]]=head[c][a]; 32 head[c][a]=size[c]++; 33 } 34 35 void dfs(int s){ 36 stx[s]=low[s]=++t; 37 S.push(s); 38 for(int i=head[0][s];~i;i=nxt[0][i]){ 39 int j=point[0][i]; 40 if(!stx[j]){ 41 dfs(j); 42 low[s]=min(low[s],low[j]); 43 } 44 else if(!scc[j]){ 45 low[s]=min(low[s],stx[j]); 46 } 47 } 48 if(low[s]==stx[s]){ 49 scccnt++; 50 while(1){ 51 int u=S.top();S.pop(); 52 scc[u]=scccnt; 53 dp[scccnt]++; 54 if(s==u)break; 55 } 56 } 57 } 58 59 void setscc(){ 60 memset(stx,0,sizeof(stx)); 61 memset(scc,0,sizeof(scc)); 62 t=scccnt=0; 63 for(int i=0;i maxx)maxx=dp[i];101 }102 int ans=0;103 printf("Case %d: %d\n",q,maxx);104 int cnt=0;105 for(int i=0;i