bzoj-1179(缩点+最短路)

题意:中文题面

解题思路:因为他能重复走且边权都正的,那么肯定一个环的是必须走完的,所以先缩点,在重新建一个图跑最长路

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int inf=0x7f7f7f7f;
const int maxn=500500;
struct node
{
    int num;
    int dist;
    node(int _num,int _dist):num(_num),dist(_dist){}
    friend bool operator<(node a,node b)
    {
        return a.dist<b.dist;
    }
};
struct Edge
{
    int next;
    int to;
    int w;
}edge[maxn],EDGE[maxn];
int low[maxn];
int dfn[maxn];
int scc_cnt;
int cnt,indexx,step,CNT;
int instack[maxn];
int sccno[maxn];
int visit[maxn];
int head[maxn],HEAD[maxn];
int w[maxn];
int val[maxn];
int dist[maxn];
int flag[maxn];
int x[maxn],y[maxn];
int tx,ty;
int n,m;
int cot,start;
int ans;
vector<int>scc[maxn];
void add(int u,int v)
{
    edge[cnt].next=head[u];
    edge[cnt].to=v;head[u]=cnt++;
}
void add2(int u,int v,int w)
{
    EDGE[CNT].next=HEAD[u];EDGE[CNT].to=v;
    EDGE[CNT].w=w;HEAD[u]=CNT++;
}
void tarjan(int u)
{
    low[u]=dfn[u]=++step;
    instack[++indexx]=u;
    visit[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(visit[v])
        {
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u])
    {
        scc_cnt++;
        scc[scc_cnt].clear();
        do
        {
            scc[scc_cnt].push_back(instack[indexx]);
            sccno[instack[indexx]]=scc_cnt;
            visit[instack[indexx]]=0;
            indexx--;
        }
        while(u!=instack[indexx+1]);
    }
    return;
}
void dij(int u)
{
    fill(dist+1,dist+1+scc_cnt,-1);
    dist[u]=0;
    priority_queue<node>que;
    que.push(node(u,dist[u]));
    while(!que.empty())
    {
        node z=que.top();que.pop();
        int now=z.num;
        for(int i=HEAD[now];i!=-1;i=EDGE[i].next)
        {
            int v=EDGE[i].to;
            if(dist[v]<dist[now]+EDGE[i].w)
            {
                dist[v]=dist[now]+EDGE[i].w;//cout<<dist[v]<<endl;
                que.push(node(v,dist[v]));
            }

        }
    }
}
void init()
{
    memset(head,-1,sizeof(head));cnt=scc_cnt=indexx=step=0;
    memset(low,0,sizeof(low));memset(dfn,0,sizeof(dfn));
    memset(visit,0,sizeof(visit));memset(HEAD,-1,sizeof(HEAD));CNT=0;
}
int main()
{
    int n,m;
    init();
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&tx,&ty);
        x[i]=tx;y[i]=ty;
        add(tx,ty);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
        tarjan(i);
    for(int i=1;i<=n;i++)
        scanf("%d",&val[i]);
    scanf("%d%d",&start,&cot);
    for(int i=1;i<=cot;i++)
        scanf("%d",&flag[i]);
    for(int i=1;i<=scc_cnt;i++)
    {
        for(int j=0;j<scc[i].size();j++)
        {
            w[i]+=val[scc[i][j]];
            if(scc[i][j]==start)
                start=i;
        }
    }
    add2(0,start,w[start]);
    for(int i=1;i<=m;i++)
    {
        if(sccno[x[i]]==sccno[y[i]])
            continue;
        else
        {
            add2(sccno[x[i]],sccno[y[i]],w[sccno[y[i]]]);
        }
    }
    dij(0);
    ans=0;
    for(int i=1;i<=cot;i++)
    {
        ans=max(ans,dist[sccno[flag[i]]]);
    }
    printf("%d\n",ans);
}

  

posted @ 2018-11-03 14:39  荒岛的龟  阅读(350)  评论(0编辑  收藏  举报