随笔 - 58,  文章 - 0,  评论 - 4,  阅读 - 3296

一、题目描述:

  给你一个 n 个点,m 条边的有向图。点带权。

  求一条路径经过的所有点的权值和最大是多少。点、边可以重复经过。

  数据范围:1n1×104,1m1×105


 二、解题思路:

  缩点板子题,不需要思路。时间复杂度 O(n+m)

  2023.9.20 更新:之前已知没有注意代码里面的这个 f 数组,照着题解直接写过了。

  现在看来其实我对 f 数组的理解并不够深刻。

  很明显的一点是:fi 表示 i 这个节点当前在不在栈中。

  如果不在栈中,说明已经作为一个新的连通块更新过了。

  而这个联通块中没有当前节点,说明当前节点不属于这个连通块。

  反正我现在已经领会到了,而且也不好解释清楚,就先这样吧。


 三、完整代码:

复制代码
 1 #include<iostream>
 2 #include<vector>
 3 #define N 10010
 4 #define M 100010
 5 using namespace std;
 6 vector <int> s[N];
 7 int n,m,l,r,cc,tot,maxx;
 8 int f[N],q[N],d[N],in[N],val[N];
 9 int dfn[N],ans[N],low[N],bel[N];
10 struct EDGE{
11     int v,nxt;
12 }edge[M];
13 int head[N],cnt;
14 void add(int u,int v)
15 {
16     edge[++cnt].v=v;
17     edge[cnt].nxt=head[u];
18     head[u]=cnt;
19 }
20 void tarjan(int u)
21 {
22     f[u]=1;q[++r]=u;dfn[u]=low[u]=++tot;
23     for(int i=head[u];i!=-1;i=edge[i].nxt)
24     {
25         int to=edge[i].v;if(!dfn[to])
26             tarjan(to),low[u]=min(low[u],low[to]);
27         else if(f[to]) low[u]=min(low[u],dfn[to]);
28         //我觉得更新low[u]原因只是为了 
29         //让u知道他自己没资格做新的联通分量的起点
30         //有点比他更适合=>极大联通子图 
31     }
32     if(dfn[u]==low[u])
33     {
34         cc++;do{
35             bel[q[r]]=cc,f[q[r]]=0;
36             s[cc].push_back(q[r]),r--;
37         }while(q[r+1]!=u);
38         //常规操作 
39     } 
40 }
41 int top_sort()
42 {
43     for(int i=1;i<=n;i++)
44         for(int j=head[i];j!=-1;j=edge[j].nxt)
45             if(bel[edge[j].v]!=bel[i])
46                 in[bel[edge[j].v]]++;
47     l=1,r=0;
48     for(int i=1;i<=cc;i++)
49         if(!in[i])
50             q[++r]=i;
51     while(l<=r)
52     {
53         int u=q[l];l++;
54         for(int i:s[u])
55             ans[u]+=val[i];
56         for(int i:s[u])
57             for(int j=head[i];j!=-1;j=edge[j].nxt)
58             {
59                 int to=bel[edge[j].v];
60                 ans[to]=max(ans[to],ans[u]);
61                 in[to]--;if(!in[to])q[++r]=to;
62             }
63     }
64     for(int i=1;i<=cc;i++)
65         maxx=max(maxx,ans[i]);
66     return maxx;
67     //感觉拓扑排序不是很必要,月赛写了个dfs也过了 
68 }
69 int main()
70 {
71     ios::sync_with_stdio(false);
72     cin.tie(0);cout.tie(0);
73     cin>>n>>m;
74     for(int i=1;i<=n;i++)
75         cin>>val[i],head[i]=-1;
76     for(int i=1,u,v;i<=m;i++)
77         cin>>u>>v,add(u,v);
78     for(int i=1;i<=n;i++)
79         if(!dfn[i])
80             tarjan(i);
81     cout<<top_sort()<<'\n';
82     return 0;
83 }
复制代码

四、写题心得:

  好的,复习了缩点。众所周知初学是在昨天。收获经验如下:

  1=>Exp++

  2 vector =>Exp++

posted on   trh0630  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示