bzoj1179: [Apio2009]Atm scc缩点+dag上dp

先把强连通缩点,然后变成了dag,dp求终点是酒吧的最长路即可,

/**************************************************************
    Problem: 1179
    User: walfy
    Language: C++
    Result: Accepted
    Time:9788 ms
    Memory:77092 kb
****************************************************************/
 
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)
 
using namespace std;
 
const double eps=1e-6;
const int N=500000+10,maxn=100000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
 
vi v[N],ans[N],sv[N];
int dfn[N],low[N];
int ind,num;
int ins[N],inans[N];
int c[N],bar[N],sb[N],sc[N];
stack<int>s;
void tarjan(int u)
{
    dfn[u]=low[u]=++ind;
    ins[u]=2;s.push(u);
    for(int i=0;i<v[u].size();i++)
    {
        int x=v[u][i];
        if(!dfn[x])
        {
            tarjan(x);
            low[u]=min(low[u],low[x]);
        }
        else if(ins[x]==2)low[u]=min(low[u],dfn[x]);
    }
    if(dfn[u]==low[u])
    {
        num++;
        while(!s.empty())
        {
            int x=s.top();
            s.pop();
            ins[x]=1;
            inans[x]=num;
            ans[num].pb(x);
            if(x==u)break;
        }
    }
}
int vis[N];
void dfs(int u)
{
    vis[u]=1;
    for(int i=0;i<sv[u].size();i++)
    {
        int x=sv[u][i];
        if(!vis[x])dfs(x);
        sb[u]|=sb[x];
    }
}
int dp[N];
int DP(int u)
{
    if(dp[u]!=-1)return dp[u];
    dp[u]=sc[u];
    for(int i=0;i<sv[u].size();i++)
    {
        int x=sv[u][i];
        if(sb[x])dp[u]=max(dp[u],DP(x)+sc[u]);
    }
    return dp[u];
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        v[a].pb(b);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjan(i);
    for(int i=1;i<=n;i++)scanf("%d",&c[i]);
    int s,p;
    scanf("%d%d",&s,&p);
    for(int i=0;i<p;i++)
    {
        int x;scanf("%d",&x);
        bar[x]=1;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<v[i].size();j++)
        {
            if(inans[v[i][j]]!=inans[i])
            {
                sv[inans[i]].pb(inans[v[i][j]]);
            }
        }
    }
    for(int i=1;i<=num;i++)
    {
        for(int j=0;j<ans[i].size();j++)
        {
            sc[i]+=c[ans[i][j]];
            if(bar[ans[i][j]])sb[i]=1;
        }
    }
    dfs(inans[s]);
//    for(int i=1;i<=num;i++)
//    {
//        for(int j=0;j<sv[i].size();j++)
//            printf("%d ",sv[i][j]);
//        puts("");
//    }
//    for(int i=1;i<=num;i++)printf("%d %d\n",sb[i],sc[i]);
    memset(dp,-1,sizeof dp);
    printf("%d\n",DP(inans[s]));
    return 0;
}
/********************
 
********************/
posted @ 2018-06-01 15:45  walfy  阅读(196)  评论(0编辑  收藏  举报