• 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
    ",ans);
    }
    

      

  • 相关阅读:
    区间DP入门
    Prime Permutation(思维好题 )
    小字辈 (bfs好题)
    博弈论小结之尼姆博弈
    Hometask
    Lucky Sum (dfs打表)
    对称博弈
    尼姆博弈
    莫队算法 ( MO's algorithm )
    Codeforces 988D Points and Powers of Two ( 思维 || 二的幂特点 )
  • 原文地址:https://www.cnblogs.com/huangdao/p/9900725.html
Copyright © 2020-2023  润新知