缩点(洛谷3387)——不会写DP 的我只好来了个SPFA

Posted Darkins

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了缩点(洛谷3387)——不会写DP 的我只好来了个SPFA相关的知识,希望对你有一定的参考价值。

  我刚开始也不知道为什么就想到肯定是缩了点后把一个新点(原图中的强连通分量)的权值赋为它所含的所有点的权值之和,没有想着去推,纯粹是题目的名字启发我这么去干的……之后用SPFA 求最大路径,然而我连的全是无向边,导致答案错误了四个点,发现错误后觉得,之前的代码居然还对了六个点才是最让人震惊的。

技术分享
 1 #include<queue>
 2 #include<stack>
 3 #include<vector>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<cstdlib>
 8 #include<cstdio>
 9 using namespace std;
10 const int N=10111;
11 int n,m,ival[N],val[N],pre[N],low[N],dfn,col[N],cnt,dgr[N],res,f[N];
12 bool ins[N];
13 vector<int> igr[N],gr[N];
14 stack<int> s;
15 void dfs(int x){
16     pre[x]=low[x]=dfn++;
17     s.push(x);ins[x]=true;
18     
19     for(int i=0;i<igr[x].size();i++)
20         if(!pre[igr[x][i]]){
21             dfs(igr[x][i]);
22             low[x]=min(low[x],low[igr[x][i]]);
23         }
24         else if(ins[igr[x][i]])low[x]=min(low[x],pre[igr[x][i]]);
25     
26     if(low[x]==pre[x]){
27         cnt++;
28         int u;
29         do{
30             u=s.top();s.pop();
31             col[u]=cnt;
32             val[cnt]+=ival[u];
33             ins[u]=false;
34         }while(u!=x);
35     }
36 }
37 
38 void spfa(int sx){
39     queue<int> q;
40     bool inq[N];memset(inq,0,sizeof inq);
41     q.push(sx);inq[sx]=true;
42     
43     res=max(res,f[sx]=val[sx]);
44     
45     while(!q.empty()){
46         int x=q.front();q.pop();inq[x]=false;
47         for(int i=0;i<gr[x].size();i++)
48             if(f[gr[x][i]]<f[x]+val[gr[x][i]]){
49                 res=max(res,f[gr[x][i]]=f[x]+val[gr[x][i]]);
50                 if(!inq[gr[x][i]])q.push(gr[x][i]);
51             }
52     }
53     
54 }
55 
56 int main(){
57     cin>>n>>m;
58     for(int i=1;i<=n;i++)cin>>ival[i];
59     while(m--){
60         int x,y;cin>>x>>y;
61         igr[x].push_back(y);
62     }
63     
64     for(int i=1;i<=n;i++)
65         if(!pre[i])
66             dfs(i);
67     
68     for(int i=1;i<=n;i++)
69         for(int j=0;j<igr[i].size();j++)
70             if(col[i]!=col[igr[i][j]]){
71                 gr[col[i]].push_back(col[igr[i][j]]);
72                 dgr[col[igr[i][j]]]++;
73             }
74     
75     for(int i=1;i<=cnt;i++)
76         if(dgr[i]==0)
77             spfa(i);
78     
79     cout<<res<<endl;
80     return 0;
81 }
Method_01

  洛谷 300ms

以上是关于缩点(洛谷3387)——不会写DP 的我只好来了个SPFA的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P3387 模板缩点

洛谷 P3387 模板缩点 题解

Tarjan缩点模板 (洛谷P3387)

luoguP3387模板缩点

洛谷P3387 缩点模板

LUOGU P3387 模板缩点 (缩点+DAG dp)