題目地址:http://poj.org/PRoblem?id=3160
思路:將所有點權值為負數的點設為0,,同一強連通分量中的點可全部選擇,因此將其看做一點。在新圖中求最長路徑即可。最長路徑:由于為給定起點,(1)從所有入度為0的點開始,進行DFS;(2)設置一虛擬節點,將其與入度為0的點相連,SPFA求最長路徑。
SPFA版
#include<cstdio>#include<vector>#include<queue>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=30000+50;const int maxm=150000+50;const int INF=0x3f3f3f3f;struct Node{ int x,y;};queue<int> q;Node e[maxm];int all,n,m,top,cnt;int s[100000],d[maxn];int vw[maxn],v[maxn];int vis[maxn],sc[maxn];int dfn[maxn],low[maxn];int scvw[maxn],dist[maxn];vector<int> g[maxn],scg[maxn];void init(){ top=all=cnt=0; memset(s,0,sizeof(s)); memset(d,0,sizeof(d)); memset(sc,0,sizeof(sc)); memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(scvw,0,sizeof(scvw)); for(int i=1; i<=n; i++) g[i].clear(),scg[i].clear();}void Tarjan(int u){ all++,dfn[u]=low[u]=all; top++,s[top]=u,vis[u]=1; for(int i=0; i<g[u].size(); i++) { int nt=g[u][i]; if(!dfn[nt]) { Tarjan(nt); low[u]=min(low[u],low[nt]); } else { if(vis[nt]) low[u]=min(low[u],dfn[nt]); } } if(low[u]==dfn[u]) { cnt++; while(s[top+1]!=u) { sc[s[top]]=cnt; vis[s[top]]=0; top--; } }}int SPFA(int s){ memset(v,0,sizeof(v)); while(!q.empty()) q.pop(); for(int i=1;i<=cnt;i++) dist[i]=-INF; v[s]=1,q.push(s),dist[s]=0; while(!q.empty()) { int now=q.front(); q.pop(),v[now]=0; for(int i=0;i<scg[now].size();i++) { int nt=scg[now][i]; if(dist[nt]<dist[now]+scvw[nt]) { dist[nt]=dist[now]+scvw[nt]; if(!v[nt]) { v[nt]=1; q.push(nt); } } } } int ans=-INF; for(int i=1;i<=cnt;i++) ans=max(ans,dist[i]); return ans;}int main(){ while(scanf("%d%d",&n,&m)!=EOF) { init(); for(int i=1; i<=n; i++) scanf("%d",&vw[i]); for(int i=0; i<m; i++) { int x,y; scanf("%d%d",&x,&y); x++,y++; e[i].x=x,e[i].y=y; g[x].push_back(y); } for(int i=1; i<=n; i++) if(!dfn[i]) Tarjan(i); for(int i=1; i<=n; i++) scvw[sc[i]]+=(vw[i]>0?vw[i]:0); for(int i=0; i<m; i++) { int x=sc[e[i].x],y=sc[e[i].y]; if(x!=y) { d[y]++; scg[x].push_back(y); } } for(int i=1; i<=cnt; i++) { if(!d[i]) scg[0].push_back(i); } printf("%d/n",SPFA(0)); } return 0;}DFS版#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=30000+50;const int maxm=150000+50;const int INF=0x3f3f3f3f;struct Node{ int x,y;};int ans;Node e[maxm];int all,n,m,top,cnt;int s[100000],d[maxn];int vw[maxn],v[maxn];int vis[maxn],sc[maxn];int dfn[maxn],low[maxn];int scvw[maxn],dist[maxn];vector<int> g[maxn],scg[maxn];void init(){ ans=-INF; top=all=cnt=0; memset(s,0,sizeof(s)); memset(d,0,sizeof(d)); memset(sc,0,sizeof(sc)); memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(scvw,0,sizeof(scvw)); for(int i=1; i<=n; i++) g[i].clear(),scg[i].clear();}void Tarjan(int u){ all++,dfn[u]=low[u]=all; top++,s[top]=u,vis[u]=1; for(int i=0; i<g[u].size(); i++) { int nt=g[u][i]; if(!dfn[nt]) { Tarjan(nt); low[u]=min(low[u],low[nt]); } else { if(vis[nt]) low[u]=min(low[u],dfn[nt]); } } if(low[u]==dfn[u]) { cnt++; while(s[top+1]!=u) { sc[s[top]]=cnt; vis[s[top]]=0; top--; } }}int dfs(int u,int tmp){ int maxx=tmp; for(int i=0;i<scg[u].size();i++) { int nt=scg[u][i]; maxx=max(maxx,dfs(nt,tmp+scvw[nt])); } return maxx;}int main(){ while(scanf("%d%d",&n,&m)!=EOF) { init(); for(int i=1; i<=n; i++) scanf("%d",&vw[i]); for(int i=0; i<m; i++) { int x,y; scanf("%d%d",&x,&y); x++,y++; e[i].x=x,e[i].y=y; g[x].push_back(y); } for(int i=1; i<=n; i++) if(!dfn[i]) Tarjan(i); for(int i=1; i<=n; i++) { scvw[sc[i]]+=(vw[i]>0?vw[i]:0); ans=max(ans,scvw[sc[i]]); } for(int i=0; i<m; i++) { int x=sc[e[i].x],y=sc[e[i].y]; if(x!=y) { d[y]++; scg[x].push_back(y); } } for(int i=1; i<=cnt; i++) { if(!d[i]) ans=max(ans,dfs(i,scvw[i])); } printf("%d/n",ans); } return 0;}
新聞熱點
疑難解答