• 清北学堂模拟赛d7t6 拯救世界


    分析:如果题目中没有环的话就是一道裸的最长路的题目,一旦有环每个城市就会被救多次火了。把有向有环图变成有向无环图只需要tarjan一边就可以了.

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int maxn = 500010;
    int n,m,head[maxn],nextt[maxn],to[maxn],tot = 1,a[maxn],S,P,p[maxn],v[maxn],vis[maxn];
    int scc[maxn],low[maxn],pre[maxn],cnt,dfs_clock,st,head2[maxn],to2[maxn],nextt2[maxn],tot2 = 1;
    bool flag[maxn];
    long long ans,d[maxn];
    stack <int> s;
    
    void add(int x,int y)
    {
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    void add2(int x,int y)
    {
        to2[tot2] = y;
        nextt2[tot2] = head2[x];
        head2[x] = tot2++;
    }
    
    void tarjan(int u)
    {
        s.push(u);
        pre[u] = low[u] = ++dfs_clock;
        for (int i = head[u];i;i = nextt[i])
        {
            int v = to[i];
            if (!pre[v])
            {
                tarjan(v);
                low[u] = min(low[u],low[v]);
            }
            else
                if (!scc[v])
                low[u] = min(low[u],pre[v]);
        }
        if (pre[u] == low[u])
        {
            cnt++;
            while (1)
            {
                int t = s.top();
                s.pop();
                v[cnt] += a[t];
                if (t == S)
                    st = cnt;
                if (p[t])
                    flag[cnt] = 1;
                scc[t] = cnt;
                if (t == u)
                    return;
            }
        }
    }
    
    void bfs()
    {
        queue <int> q;
        q.push(st);
        vis[st] = 1;
        memset(d,-1,sizeof(d));
        d[st] = v[st];
        while (!q.empty())
        {
            int u = q.front();
            vis[u]--;
            q.pop();
            for (int i = head2[u];i;i = nextt2[i])
            {
                int v2 = to2[i];
                if (d[v2] < d[u] + v[v2])
                {
                    d[v2] = d[u] + v[v2];
                    if (!vis[v2])
                    {
                        vis[v2] = 1;
                        q.push(v2);
                    }
                }
            }
        }
    }
    
    int main()
    {
        freopen("save.in","r",stdin);
        freopen("save.out","w",stdout);
        scanf("%d%d",&n,&m);
        for (int i = 1; i <= m; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if (x != y)
            add(x,y);
        }
        for (int i = 1; i <= n; i++)
            scanf("%d",&a[i]);
            scanf("%d%d",&S,&P);
        for (int i = 1; i <= P; i++)
        {
            int t;
            scanf("%d",&t);
            p[t] = 1;
        }
        for (int i = 1; i <= n; i++)
            if (!scc[i])
            tarjan(i);
    
        for (int i = 1; i <= n; i++)
        {
            for (int j = head[i];j;j = nextt[j])
            {
                int v = to[j];
                if (scc[i] != scc[v])
                    add2(scc[i],scc[v]);
            }
        }
        bfs();
        for (int i = 1; i <= cnt; i++)
            if (flag[i])
            ans = max(ans,d[i]);
        cout << ans << endl;
    
        return 0;
    }
  • 相关阅读:
    String类的操作方法
    操作日期时间类 Calendar类
    JAVA中Date类的使用
    集合方法整理
    JAVA日期——java.util.date类的操作
    关于Collections的操作方法
    java中集合
    java中继承的关系
    java
    封装继承多态-java面向对象三大特征
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7642910.html
Copyright © 2020-2023  润新知