标签:SPFA,tarjan缩点
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的单向的道路到达其中的至少一个酒吧。
算法很简单
Tarjan缩点重构图后跑一遍SPFA最长路就可以了
但是代码实现很复杂,很多细节,容易写挂题
SPFA中的初始点S,一定要赋值为belong[s]
剩下最短路中的,因为重构图,所以可以直接指向节点本身
Code
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #define rep(i,a,b) for(register int i=a;i<=b;i++) #define dep(i,a,b) for(register int i=a;i>=b;i--) #define ll long long #define mem(x,num) memset(x,num,sizeof x) #ifdef WIN32 #define LL "%I64d\n" #else #define LL "%lld\n" #endif using namespace std; inline ll read() { ll f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int maxm=5e5+6,maxn=5e5+6; int inq[maxn],que[maxn<<1],dfn[maxn],c[maxn],low[maxn],dis[maxn],v[maxn],tim=0,cnt=0,tot=0,top=0; int last[maxn],rlast[maxn],belong[maxn]; int n,m,s,p; struct edge{int to,next;}e[maxm<<1],re[maxm<<1]; #define reg(x) for(int i=last[x];i;i=e[i].next) #define ov e[i].to #define newreg(x) for(int i=rlast[x];i;i=re[i].next) #define rv re[i].to void tarjan(int x) { int now=0; dfn[x]=low[x]=++tim; que[++top]=x;inq[x]=1; reg(x) if(!dfn[ov]){tarjan(ov);low[x]=min(low[x],low[ov]);} else if(inq[ov])low[x]=min(low[x],dfn[ov]); if(low[x]==dfn[x]){ tot++; while(now!=x){ now=que[top--]; belong[now]=tot; v[tot]+=c[now]; inq[now]=0; } } } void rebuild() { cnt=0; rep(k,1,n) reg(k) if(belong[k]!=belong[ov]){ re[++cnt]=(edge){belong[k],rlast[belong[ov]]};rlast[belong[ov]]=cnt; //re[++cnt]=(edge){belong[ov],rlast[belong[k]]};rlast[belong[k]]=cnt; } } void spfa() { int head=1,tail=1; que[head]=belong[s];inq[belong[s]]=1;dis[belong[s]]=v[belong[s]]; while(head<=tail){ int now=que[head++]; newreg(now) if(dis[now]+v[rv]>dis[rv]){ dis[rv]=dis[now]+v[rv]; if(!inq[rv]){ inq[rv]=1; que[++tail]=rv; } } inq[now]=0; } } int main() { n=read(),m=read(); rep(i,1,m){ int x=read(),y=read(); e[++cnt]=(edge){x,last[y]};last[y]=cnt; //e[++cnt]=(edge){y,last[x]};last[x]=cnt; } rep(i,1,n)c[i]=read(); rep(i,1,n)if(!dfn[i])tarjan(i); s=read(),p=read(); rebuild(); spfa(); int ans=0; rep(i,1,p){ int x=read(); ans=max(ans,dis[belong[x]]); } cout<<ans<<endl; return 0; }