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