码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-11-08 22:53:45      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:min   open   pen   代码   i++   gif   0ms   hid   pac   

  我刚开始也不知道为什么就想到肯定是缩了点后把一个新点(原图中的强连通分量)的权值赋为它所含的所有点的权值之和,没有想着去推,纯粹是题目的名字启发我这么去干的……之后用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

标签:min   open   pen   代码   i++   gif   0ms   hid   pac   

原文地址:http://www.cnblogs.com/duskfire/p/7806688.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!