bzoj 1179 Atm

题目大意:

一个有向图,有些点可以作为终点,每个点有权值,每个点和边可以走很多遍,点走过之后再走点权不会计入分数

从一个点开始,求一个路径使这条路径的分数最大且终点是给定的点之一

输出这个路径长度

思路:

首先tarjan缩点

然后在新图上用spfa跑最长路(开始非常naive以为用dfs就可以

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #define ll long long 
10 #define MAXN 500100
11 #define inf 2139062143
12 using namespace std;
13 inline int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 int n,m,fst[MAXN],nxt[MAXN],to[MAXN],cnt,val[MAXN],bar[MAXN],s,Fst[MAXN],Nxt[MAXN],To[MAXN];
21 int ans,dfn[MAXN],low[MAXN],vis[MAXN],stp,top,st[MAXN],sum[MAXN],ok[MAXN],scc,bl[MAXN];
22 int dis[MAXN],q[MAXN],head,tail;
23 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
24 void Add(int u,int v) {Nxt[++cnt]=Fst[u],Fst[u]=cnt,To[cnt]=v;}
25 void tarjan(int x)
26 {
27     dfn[x]=low[x]=++stp,vis[x]=1,st[++top]=x;
28     for(int i=fst[x];i;i=nxt[i])
29         if(!dfn[to[i]]) {tarjan(to[i]);low[x]=min(low[x],low[to[i]]);}
30         else if(vis[to[i]]) low[x]=min(low[x],dfn[to[i]]);
31     if(low[x]==dfn[x])
32     {
33         scc++;int now=0;
34         while(now!=x)
35         {
36             now=st[top--],vis[now]=0,sum[scc]+=val[now],bl[now]=scc;
37             if(bar[now]) ok[scc]=1;
38         }
39     }
40 }
41 void build()
42 {
43     cnt=0;
44     for(int i=1;i<=n;i++)
45         for(int j=fst[i];j;j=nxt[j])
46             if(bl[i]!=bl[to[j]]) Add(bl[i],bl[to[j]]);
47 }
48 void spfa()
49 {
50     s=bl[s],head=tail=1,q[tail]=s,vis[s]=1;
51     while(head<=tail)
52     {
53         int x=q[head++];vis[x]=0;
54         for(int i=Fst[x];i;i=Nxt[i])
55             if(dis[To[i]]<dis[x]+sum[To[i]]) 
56             {
57                 dis[To[i]]=dis[x]+sum[To[i]];
58                 if(!vis[To[i]]) {vis[To[i]]=1,q[++tail]=To[i];}
59             }
60     }
61 }
62 int main()
63 {
64     n=read(),m=read();int a,b,t;
65     while(m--) {a=read(),b=read();add(a,b);}
66     for(int i=1;i<=n;i++) val[i]=read();
67     s=read(),t=read();
68     for(int i=1;i<=t;i++) bar[read()]=1;
69     for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
70     build();spfa();
71     for(int i=1;i<=scc;i++) if(ok[i]) ans=max(ans,dis[i]);
72     printf("%d",ans+sum[s]);
73 }
View Code
posted @ 2018-05-03 18:13  jack_yyc  阅读(172)  评论(0编辑  收藏  举报