做题记录整理图论5 P3627 [APIO2009] 抢掠计划(2022/10/11)

P3627 [APIO2009] 抢掠计划

先tarjan缩点,然后全部变成负边权,最后dij求最短路在*-1就得了(然而调了一下午)

#include<bits/stdc++.h>
#define for1(i,a,b) for(int i = a;i<=b;i++)
#define ll long long
#define mp(a,b) make_pair(a,b)
using namespace std;
const int inf = 1e9;
struct node{
	int nex;
	int to;
}e[500005];
int a[500005],id[500005],sum[500005],zhan[500005],top,kg,k;
int dis[500005],hd[500005],cnt;
vector <int> h[500005],hh[500005];
int p[500005],dfn[500005],low[500005],jl;
bool ins[500005],vis[500005];
int n,m,u,v,S,P,ans;
queue <int> q;
void ru(int x,int y) 
{
    e[++cnt].to = y;
    e[cnt].nex = hd[x];
    hd[x]=cnt;
}

void tarjan (int x) 
{
    dfn[x]=low[x]=++jl;
    zhan[++top]=x;
    ins[x]=1;
    for(int i = hd[x];i;i=e[i].nex) 
	{
		int v=e[i].to;
        if (!dfn[v])
            tarjan (v), 
			low[x] = min(low[x], low[v]);
        else if (ins[v])
            low[x] = min(low[x], dfn[v]);
    }
    if(dfn[x] == low[x]) 
	{
        ++kg;
        do {
            k = zhan[top--];
            ins[k] = 0;
            id[k] = kg;
            sum[kg] += a[k];
        } while(x!=k);
    }
}

int main() 
{
    cin>>n>>m;
    for1(i,1,m)
	{
    	scanf("%d%d",&u,&v);
	    ru(u,v);
	}
    for1(i,1,n) scanf("%d",&a[i]);
    
    for1(i,1,n)
        if (!dfn[i]) 
		    tarjan (i);
		    
    cin>>S>>P;
    for1(i,1,P)
        scanf("%d",&p[i]);
        
    
	for1(i,1,n)
        for(int j = hd[i]; j; j = e[j].nex)
            if(id[i] != id[e[j].to])
                h[id[i]+kg].push_back(id[e[j].to]),hh[id[i]+kg].push_back(0);
                
    for1(i,1,kg)
        h[i].push_back(i+kg),hh[i].push_back(sum[i]);
        
    memset(dis,-inf,sizeof(dis));
    vis[id[S]] =1,dis[id[S]] = 0;
    q.push(id[S]);
    
    while(!q.empty ()) 
	{
        int x = q.front();
        q.pop ();
		vis[x] = 0;
        for(int i = 0;i<h[x].size();i++) 
		{
            int v=h[x][i],w=hh[x][i];
            if(dis[v] < dis[x] + w) 
			{
                dis[v] = dis[x]+w;
                if(!vis[v]) 
				{
                    q.push(v);
                    vis[v] = 1;
                }
            }
        }
    }
    for1(i,1,P)
        ans=max(ans,dis[id[p[i]]+kg]);
    printf ("%d\n",ans);
}
posted @ 2022-10-11 19:37  yyx525jia  阅读(31)  评论(0)    收藏  举报