zoukankan      html  css  js  c++  java
  • bzoj 1179 tarjan+spfa

      首先我们可以将这个图缩成DAG,那么问题中的路线就可以简化为DAG中的一条链,那么我们直接做一遍spfa就好了。

      反思:开始写的bfs,结果bfs的时候没有更新最大值,而是直接赋的值,后来发现不能写bfs,因为每个点可能进队好多次,当让可以改成循环队列什么的bfs,然后我就改成了spfa,伪的spfa,就是判一下这个点是不是更优了,更优才入队。

    /**************************************************************
        Problem: 1179
        User: BLADEVIL
        Language: C++
        Result: Accepted
        Time:6640 ms
        Memory:109356 kb
    ****************************************************************/
     
    //By BLADEVIL
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define maxm 2000010
    #define maxn 2000010
     
    using namespace std;
     
    int n,m,s,tot,time,num,p,l;
    int pre[maxm],other[maxm],last[maxn],key[maxn],flag[maxn];
    int stack[maxn],dfn[maxn],low[maxn],vis[maxn],col[maxn],que[maxn],w[maxn];
     
    void connect(int x,int y) {
        pre[++l]=last[x];
        last[x]=l;
        other[l]=y;
    }
     
    void dfs(int x) {
        stack[++tot]=x; vis[x]=1;
        dfn[x]=low[x]=++time;
        for (int p=last[x];p;p=pre[p]) {
            if (!dfn[other[p]]) 
                dfs(other[p]),low[x]=min(low[x],low[other[p]]); else
            if (vis[other[p]]) low[x]=min(low[x],dfn[other[p]]);
        }
        if (dfn[x]==low[x]) {
            int cur=-1;
            num++;
            while (cur!=x) {
                cur=stack[tot--];
                vis[cur]=0;
                col[cur]=num;
            }
        }
    }
     
    int main() {
        scanf("%d%d",&n,&m); num=n;
        for (int i=1;i<=m;i++) {
            int x,y; scanf("%d%d",&x,&y);
            connect(x,y);
        }
        for (int i=1;i<=n;i++) scanf("%d",&key[i]);
        scanf("%d%d",&s,&p);
        while (p--) {
            int x; scanf("%d",&x);
            flag[x]=1;
        }
        dfs(s);
        for (int i=1;i<=n;i++) {
            for (int p=last[i];p;p=pre[p]) if (col[i]!=col[other[p]]) connect(col[i],col[other[p]]);
        }
        for (int i=1;i<=n;i++) key[col[i]]+=key[i],flag[col[i]]|=flag[i];
        memset(vis,0,sizeof vis);
        que[1]=col[s]; vis[col[s]]=1; w[col[s]]=key[col[s]];
        int h=0,t=1,ans=0;
        while (h<t) {
            int cur=que[++h];
            if (flag[cur]) ans=max(ans,w[cur]);
            for (int p=last[cur];p;p=pre[p]) {
                if (w[cur]+key[other[p]]>w[other[p]]) {
                w[other[p]]=max(w[other[p]],w[cur]+key[other[p]]);
                que[++t]=other[p]; vis[other[p]]=1;
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    623. Add One Row to Tree 将一行添加到树中
    771. Jewels and Stones 珠宝和石头
    216. Combination Sum III 组合总数三
    384. Shuffle an Array 随机播放一个数组
    382. Linked List Random Node 链接列表随机节点
    向github项目push代码后,Jenkins实现其自动构建
    centos下安装Jenkins
    python提取批量文件内的指定内容
    批处理实现:批量为文件添加注释
    python抓取每期双色球中奖号码,用于分析
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3650562.html
Copyright © 2011-2022 走看看