LightOJ1417 Forwarding Emails(强连通分量+缩点+记忆化搜索)

题目大概是,每个人收到信息后会把信息发给他认识的一个人如此下去,问一开始要把信息发送给谁这样看到信息的人数最多。

  • 首先找出图中的SCC并记录每个SCC里面的点数,如果传到一个SCC,那么里面的人都可以看到信息。
  • 然后SCC缩点后就形成DAG,直接记忆化搜索,d(u)搜索从u点出发开始传最多能传多少人。
  • 最后就是找答案了。
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define MAXN 55555
 6 #define MAXM 55555
 7 
 8 struct Edge{
 9     int u,v,next;
10 }edge[MAXM];
11 int NE,head[MAXN];
12 void addEdge(int u,int v){
13     edge[NE].u=u; edge[NE].v=v; edge[NE].next=head[u];
14     head[u]=NE++;
15 }
16 
17 int size[MAXN],bn,belong[MAXN];
18 int stack[MAXN],top;
19 bool instack[MAXN];
20 int dn,dfn[MAXN],low[MAXN];
21 void tarjan(int u){
22     dfn[u]=low[u]=++dn;
23     stack[++top]=u; instack[u]=1;
24     for(int i=head[u]; i!=-1; i=edge[i].next){
25         int v=edge[i].v;
26         if(dfn[v]==0){
27             tarjan(v);
28             low[u]=min(low[u],low[v]);
29         }else if(instack[v]){
30             low[u]=min(low[u],dfn[v]);
31         }
32     }
33     if(dfn[u]==low[u]){
34         int v; ++bn;
35         do{
36             v=stack[top--];
37             instack[v]=0;
38             belong[v]=bn;
39             ++size[bn];
40         }while(u!=v);
41     }
42 }
43 
44 int d[MAXN];
45 int dfs(int u){
46     if(d[u]) return d[u];
47     int res=size[u],tmp=0;
48     for(int i=head[u]; i!=-1; i=edge[i].next){
49         int v=edge[i].v;
50         tmp=max(tmp,dfs(v));
51     }
52     return d[u]=res+tmp;
53 }
54 
55 int main(){
56     int t,n,a,b;
57     scanf("%d",&t);
58     for(int cse=1; cse<=t; ++cse){
59         NE=0;
60         memset(head,-1,sizeof(head));
61         scanf("%d",&n);
62         for(int i=0; i<n; ++i){
63             scanf("%d%d",&a,&b);
64             addEdge(a,b);
65         }
66 
67         top=bn=dn=0;
68         memset(instack,0,sizeof(instack));
69         memset(dfn,0,sizeof(dfn));
70         memset(size,0,sizeof(size));
71         for(int i=1; i<=n; ++i){
72             if(dfn[i]==0) tarjan(i);
73         }
74 
75         int tmp=NE; NE=0;
76         memset(head,-1,sizeof(head));
77         for(int i=0; i<tmp; ++i){
78             int u=belong[edge[i].u],v=belong[edge[i].v];
79             if(u==v) continue;
80             addEdge(u,v);
81         }
82 
83         memset(d,0,sizeof(d));
84         int mx=0;
85         for(int i=1; i<=bn; ++i){
86             mx=max(mx,dfs(i));
87         }
88         for(int i=1; i<=n; ++i){
89             if(d[belong[i]]==mx){
90                 printf("Case %d: %d\n",cse,i);
91                 break;
92             }
93         }
94     }
95     return 0;
96 }

 

转载于:https://www.cnblogs.com/WABoss/p/5158884.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值