这题一看就是缩点,但是缩完点怎么办呢?首先我们把所有的包含酒吧的缩点找出来,打上标记,然后建立一张新图,
每个缩点上的点权就是他所包含的所有点的点权和。但是建图的时候要注意,每一对缩点之间可能有多条边,所以我们可以先把重边去除一下,在建立新图,具体操作如下:
 1 for(int i=1;i<=n;i++)
  2     {
  3         if(vis[i]==0) continue;
  4         for(int j=last[i];j;j=g[j].next)
  5         {
  6             int v=g[j].to;
  7             if(g[i].co!=g[v].co&&vis[v]==1)
  8             {
  9                 e[++cnt].a=g[i].co;
 10                 e[cnt].b=g[v].co;
 11             }
 12         }
 13     }
 14     sort(e+1,e+cnt+1,cmp);
 15     for(int i=1;i<=cnt;i++)
 16     {
 17         if(e[i].a!=e[i-1].a||e[i].b!=e[i-1].b)
 18         {
 19             add1(e[i].a,e[i].b);
 20         }                
 21     }
具体思路就是先枚举所有点和所有边,如果两个点不属于同一个强联通分量,那么就用e来把边存一下,然后对e进行排序
,去重,再建图。
建完图之后就好办了,可以跑spfa单源最长路,也可以dp,因为最后一定会终止在酒吧,所以就取所有打过标记的节点的最大值就好了。
最后附上代码:
  1 #include
   2 #include
   3 #include
   4 #include
   5 #include
   6 #include
   7 #define maxn 500005
   8 using namespace std;
   9 struct edge
  10 {
  11     int next;
  12     int to;
  13     int co;
  14 }g[maxn];
  15 
  16 struct edge1
  17 {
  18     int next;
  19     int to;
  20 }g1[maxn];
  21 struct edhe
  22 {
  23     int a,b;
  24 }e[maxn];
  25 
  26 
  27 inline int read()
  28 {
  29     char c=getchar();
  30     int res=0,x=1;
  31     while(c<'0'||c>'9')
  32     {
  33         if(c=='-')
  34         x=-1;
  35         c=getchar();
  36     }
  37     while(c>='0'&&c<='9')
  38     {
  39         res=res*10+(c-'0');
  40         c=getchar();
  41     }
  42     return x*res;
  43 }
  44 
  45 int n,m,aa,bb,num,s,p,tot,top,col,num1,ans,ae,cnt;
  46 int last[maxn],a[maxn],b[maxn],dfn[maxn],st[maxn],low[maxn];
  47 int shu[maxn],d[maxn],last1[maxn],sum[maxn],vis[maxn];
  48 
  49 inline void add(int from,int to)
  50 {
  51     g[++num].next=last[from];
  52     g[num].to=to;
  53     last[from]=num;
  54 }
  55 
  56 inline void add1(int from,int to)
  57 {
  58     g1[++num1].next=last1[from];
  59     g1[num1].to=to;
  60     last1[from]=num1;
  61 }
  62 
  63 inline void tarjan(int u)
  64 {
  65     low[u]=dfn[u]=++tot;
  66     st[++top]=u;
  67     for(int i=last[u];i;i=g[i].next)
  68     {
  69         int v=g[i].to;
  70         if(!dfn[v])
  71         {
  72             tarjan(v);
  73             if(low[v]
  75         }
  76         else if(!g[v].co)
  77         {
  78             if(dfn[v]
  80         }
  81     }
  82     if(low[u]==dfn[u])
  83     {
  84         g[u].co=++col;
  85         while(st[top]!=u)
  86         {
  87             g[st[top]].co=col;
  88             top--;
  89         }
  90         top--;
  91     }
  92 }
  93 
  94 void dfs(int x)
  95 {
  96     for(int i=last1[x];i;i=g1[i].next)
  97     {
  98         int v=g1[i].to;
  99         if(sum[x]+shu[v]>sum[v])
 100         {
 101             sum[v]=sum[x]+shu[v];
 102             dfs(v);
 103         }
 104     }
 105 }
 106 
 107 bool cmp(edhe a,edhe b)
 108 {
 109     if(a.a==b.a)
 110     {
 111         return a.b
 113     else return a.a
 115 
 116 int main()
 117 {
 118     n=read();
 119     m=read();
 120     for(int i=1;i<=m;i++)
 121     {
 122         aa=read();bb=read();
 123         add(aa,bb);
 124     }
 125     for(int i=1;i<=n;i++)
 126     {
 127         a[i]=read();
 128     }
 129     s=read();p=read();
 130     for(int i=1;i<=p;i++)
 131     {
 132         aa=read();
 133         b[aa]=1;
 134     }
 135     for(int i=1;i<=n;i++)
 136     {
 137         if(!dfn[i])
 138         tarjan(i);
 139     }
 140     for(int i=1;i<=n;i++)
 141     {
 142         shu[g[i].co]+=a[i];
 143         if(b[i]==1)
 144         {
 145             d[g[i].co]=1;
 146         }
 147     }
 148     for(int i=1;i<=n;i++)
 149     {
 150         if(vis[i]==0) continue;
 151         for(int j=last[i];j;j=g[j].next)
 152         {
 153             int v=g[j].to;
 154             if(g[i].co!=g[v].co)
 155             {
 156                 e[++cnt].a=g[i].co;
 157                 e[cnt].b=g[v].co;
 158             }
 159         }
 160     }
 161     sort(e+1,e+cnt+1,cmp);
 162     for(int i=1;i<=cnt;i++)
 163     {
 164         if(e[i].a!=e[i-1].a||e[i].b!=e[i-1].b)
 165         {
 166             add1(e[i].a,e[i].b);
 167         }                
 168     }
 169     sum[g[s].co]=shu[g[s].co];
 170     dfs(g[s].co);
 171     for(int i=1;i<=col;i++)
 172     {
 173         if(d[i]==1)
 174         {
 175             if(ans
 177         }
 178     }
 179     printf("%d",ans);
 180     return 0;
 181 }