国家一级爬山运动员h10今天获得了一张有着密密麻麻标记的地图,在好奇心的驱使下,他又踏上了去爬山的路。
对于爬山,h10有一个原则,那就是不走回头路,于是他把地图上的所有边都标记成了有向边。他决定从点S出发,每到达一个新的节点他就可以获得一定的成就值。同时h10又是一个很珍惜时间的运动员,他不希望这次爬山的成就值白白浪费,所以最后他一定要在一个存档点停下,保存自己的成就值。
请你计算出在此次爬山运动中h10能够得到的最大成就值。保证h10能走到存档点。
样例输入:
第一行两个整数 N,M,表示点数和边数。
接下来 M 行,每行两个整数 u,v,表示u到v有一条有向边(没有自环)。
第 M+2 行 N 个正整数,表示每个点的成就值。
接下来一行两个整数 S,p,表示出发点和存档点个数。
下面一行 p 个整数,表示存档点。
5 7
5 1
3 1
2 5
3 5
4 3
4 2
4 5
7 6 3 2 2
4 3
1 5 2
样例输出:
一个正整数,表示最大成就值。
17
数据范围:
对于 30% 的数据, N,M≤1000,并且地图为有向无环图。
对于 100% 的数据, N,M≤500000。(数据有梯度,注意答案的大小)
给一个有向有环图,每个点有个贡献,第一次到达此点可以获得这个贡献,问从一点出发,到达一些特定点中,能够获得最大的贡献是多少。
没有环的很好处理,一遍最短路即可。
至于环,很容易想到缩点,将一个环缩为一点,毕竟以前打过,在一遍最短路即可。
然而,此题tarjan却爆栈!需要手工栈,然而我并没有打过手工栈,所以没有打,就GG了几个点。
如上。
#include
#include
#include
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int maxn=1e5*5+2,mo=1e6+5;
int fre[maxn],next[maxn],go[maxn],a[maxn*2][3],t[maxn],dfn[maxn],low[maxn];
int now[maxn],hg[mo],keep[maxn],sta[maxn];
int n,m,S,p,num,k,top,tt,ttop;
bool bz[maxn*3],sbz[maxn];
ll ans,pro[maxn*3],dis[maxn*3];
stack<int>st;
void add(int x,int y)
{
go[++num]=y;
next[num]=fre[x];
fre[x]=num;
}
void tarjan(int x)
{
dfn[x]=++k; low[x]=k;
sbz[x]=true; sta[++sta[0]]=x;
st.push(x);
while (!st.empty()){
int u=st.top();
int i=fre[u];
if (now[u]){
i=now[u];
low[u]=min(low[u],low[go[i]]);
i=next[i];
}
while (i){
if (!dfn[go[i]]) {
now[u]=i;
dfn[go[i]]=low[go[i]]=++k;
sbz[go[i]]=true;
st.push(go[i]);
sta[++sta[0]]=go[i];
break;
}
else if (sbz[go[i]]) low[u]=min(low[u],dfn[go[i]]);
i=next[i];
}
if (u==st.top()){
++tt; int j=0;
if(dfn[u]==low[u]){
while (sta[sta[0]]!=u){
int k=sta[sta[0]];
++j;
t[k]=tt;
pro[tt]+=pro[k];
sbz[k]=false;
--sta[0];
}
sbz[u]=false;
--sta[0];
++j;
if (j==1) --tt;
else {
t[u]=tt;
pro[tt]+=pro[u];
}
}
st.pop();
}
}
}
void spfa(int x)
{
dis[x]=pro[x]; bz[x]=true; hg[1]=x;
int h=0,t=1;
while (h!=t){
h=h%mo+1;
int u=hg[h];
bz[u]=false;
int i=fre[u];
while (i){
if (dis[go[i]]if (!bz[go[i]]){
bz[go[i]]=true;
t=t%mo+1;
hg[t]=go[i];
}
}
i=next[i];
}
}
}
int main()
{
//freopen("T.in","r",stdin);
scanf("%d%d",&n,&m);
fo(i,1,m){
scanf("%d%d",&a[i][1],&a[i][2]);
add(a[i][1],a[i][2]);
}
fo(i,1,n) scanf("%d",&pro[i]);
scanf("%d%d",&S,&p);
fo(i,1,p) scanf("%d",&keep[i]);
tt=n;
tarjan(S);
fo(i,1,max(n,num)){
fre[i]=0; go[i]=0; next[i]=0;
}
num=0;
fo(i,1,m){
if (!t[a[i][1]] && !t[a[i][2]]) add(a[i][1],a[i][2]);
else if (t[a[i][1]] && !t[a[i][2]] ) add(t[a[i][1]],a[i][2]);
else if (!t[a[i][1]] && t[a[i][2]]) add(a[i][1],t[a[i][2]]);
else if (t[a[i][1]]&&t[a[i][2]]&&t[a[i][1]]!=t[a[i][2]])
add(t[a[i][1]],t[a[i][2]]);
}
if (!t[S]) spfa(S); else spfa(t[S]);
fo(i,1,p)
if (t[keep[i]]){
if (anselse if (ansprintf("%lld",ans);
}