hihoCoder#1185 : 连通性·三 tarjan求强联通分量 缩点 dfs/拓扑排序求路径和最大值...

题目链接:

http://hihocoder.com/problemset/problem/1185#

题意:

n个点,每个点有一个权值,m条有向边,从1出发,每走到一个点, 就吃掉这个点的草,当没有可以到达的草场或是能够到达的草场都已经被吃光了之后就要返回到1了。求最多可以吃掉多少草。

思路:

提示里面讲的挺好的

如果草场是一个强连通图,那么我们只要走到任意一点,就可以把其他所有的草场都走一遍,并且可以选择任意一个点作为终点。所以把强联通块缩成一个点

因为一个强连通块会被缩成一个点,那么我们可以直接建立一个新的图,这个图中的点对应的是每一个强连通块。若原图中存在边(u,v),连接了属于强连通分量A的点u和属于强连通分量B的点v,那么我们就在新图中建立一条边(A,B)。

先根据原图找到所有的强连通分量,然后再根据原图边的关系建立新的图,之后再用拓扑排序来处理就可以得到最终结果。

缩点之后就没有环了,也就是说我们要求的答案在某条链上面,可以直接dfs下去,找到最大值,也可以用拓扑排序

拓扑排序就是每次取入度为0的点,用它去更新它所能到达的点的最大值,我们不能直接用点的权值更新这个点的答案,因为当有多条边指向一个点的时候,可能会有重复的权值加进来,比如一个点通过两条不同的路径到达另一个点,a->b,b->c, a->d,d->c, 那么a点的权值会在c点加两次,所以我们需要新开一个数组表示答案,本来的权值要保留。

代码:

dfs:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define MS(a) memset(a,0,sizeof(a))
 5 #define MP make_pair
 6 #define PB push_back
 7 const int INF = 0x3f3f3f3f;
 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
 9 inline ll read(){
10     ll x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 //
16 const int maxn = 1e5+10;
17 
18 int n,m,tot;
19 vector<int> g[maxn];
20 int low[maxn],dfn[maxn],vis[maxn],ins[maxn],r[maxn],w[maxn];
21 stack<int> s;
22 
23 void tarjan(int u){
24     vis[u] = ins[u] = 1;
25     dfn[u] = low[u] = ++tot;
26     s.push(u);
27     for(int i=0; i<(int)g[u].size(); i++){
28         int v = g[u][i];
29         if(!vis[v]){
30             tarjan(v);
31             low[u] = min(low[u],low[v]);
32         }else if(ins[v]){
33             low[u] = min(low[u],dfn[v]);
34         }
35     }
36     int sum = 0;
37     if(dfn[u] == low[u]){
38         int t;
39         do{
40             t = s.top();
41             s.pop();
42             ins[t] = 0;
43             sum += w[t];
44             r[t] = u;
45         }while(u != t);
46         w[u] = sum;
47     }
48 }
49 
50 void upd(){
51     for(int i=1; i<=n; i++){
52         if(i != r[i]){
53             for(int j=0; j<(int)g[i].size(); j++){
54                 int v = g[i][j];
55                 if(v != r[i]) g[r[i]].push_back(v);
56             }
57         }
58     }
59 }
60 
61 int ans,sum;
62 void dfs(int u){
63     sum += w[u];
64     for(int i=0; i<(int)g[u].size(); i++){
65         int v = g[u][i];
66         if(u == r[v]) continue;
67         dfs(v);
68     }
69     ans = max(ans,sum);
70     sum -= w[u];
71 }
72 
73 int main(){
74     cin >> n >> m;
75     for(int i=1; i<=n; i++)
76         scanf("%d",&w[i]);
77     for(int i=0; i<m; i++){
78         int u,v; scanf("%d%d",&u,&v);
79         g[u].push_back(v);
80     }
81     for(int i=1; i<=n; i++)
82         if(!dfn[i]) tarjan(1);
83     upd();
84     dfs(1);
85 
86     cout << ans << endl;
87 
88     return 0;
89 }

拓扑排序:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 #define MS(a) memset(a,0,sizeof(a))
  5 #define MP make_pair
  6 #define PB push_back
  7 const int INF = 0x3f3f3f3f;
  8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
  9 inline ll read(){
 10     ll x=0,f=1;char ch=getchar();
 11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 13     return x*f;
 14 }
 15 //
 16 const int maxn = 1e5+10;
 17 
 18 int n,m,tot;
 19 vector<int> g[maxn];
 20 int low[maxn],dfn[maxn],vis[maxn],ins[maxn],r[maxn],w[maxn],pp[maxn],in[maxn];
 21 
 22 void tarjan(int u){
 23     vis[u] = ins[u] = 1;
 24     dfn[u] = low[u] = ++tot;
 25     s.push(u);
 26     for(int i=0; i<(int)g[u].size(); i++){
 27         int v = g[u][i];
 28         if(!vis[v]){
 29             tarjan(v);
 30             low[u] = min(low[u],low[v]);
 31         }else if(ins[v]){
 32             low[u] = min(low[u],dfn[v]);
 33         }
 34     }
 35     int sum = 0;
 36     if(dfn[u] == low[u]){
 37         int t;
 38         do{
 39             t = s.top();
 40             s.pop();
 41             ins[t] = 0;
 42             sum += w[t];
 43             r[t] = u;
 44         }while(u != t);
 45         w[u] = sum;
 46     }
 47 }
 48 
 49 void upd(){
 50     for(int i=1; i<=n; i++){
 51         if(i != r[i]){
 52             for(int j=0; j<(int)g[i].size(); j++){
 53                 int v = g[i][j];
 54                 if(v != r[i]) g[r[i]].push_back(v);
 55             }
 56         }
 57     }
 58 }
 59 void cal(){
 60     for(int i=1; i<=n; i++){
 61         if(i != r[i]) continue;
 62         for(int j=0; j<(int)g[i].size(); j++){
 63             int v = g[i][j];
 64             if(r[v] == r[i]) continue;
 65             // cout << v << " " << r[v] << endl;
 66             in[r[v]]++;
 67         }
 68     }
 69 }
 70 
 71 int ans;
 72 
 73 int main(){
 74     cin >> n >> m;
 75     for(int i=1; i<=n; i++)
 76         scanf("%d",&w[i]);
 77     for(int i=0; i<m; i++){
 78         int u,v; scanf("%d%d",&u,&v);
 79         g[u].push_back(v);
 80     }
 81     for(int i=1; i<=n; i++)
 82         if(!dfn[i]) tarjan(1);
 83     upd(); cal();
 84     // for(int i=1; i<=n; i++)
 85     //     cout << in[i] << endl;
 86     queue<int> q;
 87     q.push(r[1]);
 88     pp[1] = w[r[1]];
 89     while(!q.empty()){
 90         int u = q.front(); q.pop();
 91         if(u != r[u]) continue;
 92         ans = max(ans,pp[u]);
 93         for(int i=0; i<(int)g[u].size(); i++){
 94             int v = g[u][i];
 95             if(u == r[v]) continue;
 96             in[v]--;
 97             pp[v] = max(pp[v],w[v]+pp[u]);
 98             if(in[v] == 0) q.push(v);
 99         }
100     }
101 
102     cout << ans << endl;
103 
104     return 0;
105 }

 

转载于:https://www.cnblogs.com/yxg123123/p/6955832.html

weixin151云匹面粉直供微信小程序+springboot后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值