1. 程式人生 > >縮點(洛谷3387)——不會寫DP 的我只好來了個SPFA

縮點(洛谷3387)——不會寫DP 的我只好來了個SPFA

hid color hide 強連通分量 algorithm onclick tor play emp

  我剛開始也不知道為什麽就想到肯定是縮了點後把一個新點(原圖中的強連通分量)的權值賦為它所含的所有點的權值之和,沒有想著去推,純粹是題目的名字啟發我這麽去幹的……之後用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