bzoj1179: [Apio2009]Atm

tarjan缩点就是DAG上求最长路把。。。然而我并不会求。。。只会写spfa了。。。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next)
#define qaq(x) for(edge *o=h[x];o;o=o->next)
int read(){
    int x=0;char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) x=x*10+c-‘0‘,c=getchar();
    return x;
}
const int nmax=500005;
const int inf=0x7f7f7f7f;
struct edge{
    int to;edge *next;
};
edge es[nmax<<1],*pt=es,*head[nmax],*h[nmax];
void add(int u,int v){
    pt->to=v;pt->next=head[u];head[u]=pt++;
}
int pre[nmax],a[nmax],scc[nmax],dfs_clock,scc_cnt;
stack<int>s;
int dfs(int x){
    int lowu=pre[x]=++dfs_clock;s.push(x);
    qwq(x){
        if(!pre[o->to]) lowu=min(lowu,dfs(o->to));
        else if(!scc[o->to]) lowu=min(lowu,pre[o->to]);
    }
    if(lowu==pre[x]){
        int o;scc_cnt++;
        while(1){
            o=s.top();s.pop();scc[o]=scc_cnt;
            if(o==x) break;
        }
    }
    return lowu;
}
void adde(int u,int v){
    pt->to=v;pt->next=h[u];h[u]=pt++;
}
int dist[nmax];bool inq[nmax];
queue<int>q;
void spfa(int s){
    q.push(s);inq[s]=1;dist[s]=a[s];
    int tx,td;
    while(!q.empty()){
        tx=q.front();q.pop();inq[tx]=0;
        qaq(tx) if(dist[o->to]<dist[tx]+a[o->to]){
            dist[o->to]=dist[tx]+a[o->to];
            if(!inq[o->to]) q.push(o->to),inq[o->to]=1;
        }
    }
}
int main(){
    int n=read(),m=read(),u,v;
    rep(i,1,m) u=read(),v=read(),add(u,v);
    rep(i,1,n) if(!pre[i]) dfs(i);
    rep(i,1,n) u=read(),a[scc[i]]+=u;
    rep(i,1,n) {
        qwq(i) {
            u=scc[i],v=scc[o->to];
            if(u!=v) adde(u,v);
        }
    }
    int s=read(),tm=read(),ans=0;
    spfa(scc[s]);
    rep(i,1,tm) u=read(),ans=max(ans,dist[scc[u]]);
    printf("%d\n",ans);
    return 0;
}

  

1179: [Apio2009]Atm

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 2754  Solved: 1143
[Submit][Status][Discuss]

Description

Input

第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号。接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。接下来一行包含两个整数S、P,S表示市中心的编号,也就是出发的路口。P表示酒吧数目。接下来的一行中有P个整数,表示P个有酒吧的路口的编号

Output

输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数。

Sample Input

6 7
1 2
2 3
3 5
2 4
4 1
2 6
6 5
10
12
8
16
1 5
1 4
4
3
5
6

Sample Output

47

HINT

50%的输入保证N, M<=3000。所有的输入保证N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。

Source

[Submit][Status][Discuss]

时间: 2024-10-19 21:57:59

bzoj1179: [Apio2009]Atm的相关文章

BZOJ1179 : [Apio2009]Atm 缩点+spfa

1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 2069  Solved: 826[Submit][Status][Discuss] Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来

tarjan+spfa最短路 BZOJ1179 [Apio2009] Atm

1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 3641  Solved: 1552[Submit][Status][Discuss] Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下

【强连通分量&#183;Tarjan】bzoj1179: [Apio2009]Atm

新博的第一发! 因为这几天切了几道强连通分量,所以从这里begin [题目描述] Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定,在每个路口都设立了一个Siruseri 银行的ATM 取款机.令人奇怪的是,Siruseri的酒吧也都设在路口,虽然并不是每个路口都设有酒吧.Banditji 计划实施Siruseri 有史以来最惊天动地的ATM 抢劫.他将从市中心出发,沿着单向道路行驶,抢劫所有他途径的ATM 机,最终他将在一个酒吧庆祝他的胜利.使用高超的黑客技术,他获

【强连通分量+spfa】Bzoj1179 Apio2009 Atm

Description Sulotion 显然缩强连通分量,然后求最长路,虽然是DAG但还是有点麻烦,于是用了spfa. Code 重建图_数组写错好多次,感觉做这题也就是练了一下实现. 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=5e+5; 5 6 int pre[maxn],low[maxn],clock; 7 int scc[maxn],val[maxn],c

[BZOJ1179] [Apio2009]Atm(tarjan缩点 + spfa)

传送门 题意 N个点M条边的有向图 每个点有点权 从某一个结点出发 问能获得的最大点权和 一个点的点权最多被计算一次 N<=500000 M<=500000 思路 先tarjan缩点,然后就形成一个dag,无环,所以直接spfa求最长路就行. 也可以先缩点,然后拓扑排序 + dp 搞. 代码 1 #include <map> 2 #include <queue> 3 #include <stack> 4 #include <cstdio> 5 #

【强联通分量缩点】【最短路】【spfa】bzoj1179 [Apio2009]Atm

缩点后转化成 DAG图上的单源最长路问题.spfa/dp随便. 1 #include<cstdio> 2 #include<queue> 3 #include<algorithm> 4 #include<vector> 5 #include<cstring> 6 using namespace std; 7 int cmp[500001],sum,n,m,Us[500001],Vs[500001],t,w[500001],sta,k,ans,di

[BZOJ1179][APIO2009][强连通分量Tarjan+spfa]ATM

[BZOJ1179][APIO2009]ATM Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S.P,S表示市中心的编号,也就是出发的路口.P表示酒吧数目.接下来的一行中有P个整数,表示P个有酒吧的路口的编号 Output 输出一个整数,表示Banditji从市中心开始到某个

1179: [Apio2009]Atm

1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1629  Solved: 615[Submit][Status] Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S

【BZOJ-1179】Atm Tarjan + SPFA

1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 2407  Solved: 993[Submit][Status][Discuss] Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来