BZOJ1179(Apio2009)[Atm]--Tarjan+最短路

【链接】
bzoj1179

【解题报告】

Tarjan裸题。

再刷一遍最短路即可。

#include<cstdio>
#include<cstring>
const int maxn=500005,maxm=500005,maxp=1005;
int n,m,P,ti,st,who[maxp],mo[maxn],father[maxn],E[2],son[maxm][2],nxt[maxm][2],lnk[maxn][2],ans,distz[maxn],len_b;
int dfn[maxn],low[maxn],stack_[maxn],top,que[maxn];
bool instack[maxn],vis[maxn];
bool Eoln(char ch) {return ch==10||ch==13||ch==EOF;}
inline int readi(int &x)
{
    int tot=0,f=1;
    char ch=getchar();if (ch==EOF) return 2;
    while ('9'<ch||ch<'0') {if (ch=='-') f=-f;ch=getchar();}
    while ('0'<=ch&&ch<='9') tot=tot*10+ch-48,ch=getchar();
    x=tot*f;
    return Eoln(ch);
}
int min2(int x,int y) {return x<y? x:y;}
void Tarjan(int x)
{
    int j,y;
    dfn[x]=++ti;low[x]=ti;instack[x]=true;stack_[++top]=x;
    for (j=lnk[x][0];j;j=nxt[j][0])
        if (dfn[son[j][0]]==0)
        {
            Tarjan(son[j][0]);
            low[x]=min2(low[x],low[son[j][0]]);
        } else if (instack[son[j][0]]) low[x]=min2(low[x],dfn[son[j][0]]);
    if (dfn[x]==low[x])
        do
        {
            y=stack_[top--];
            instack[y]=false;father[y]=x;
            if (x!=y) mo[x]+=mo[y];
        } while (x!=y);
}
void swapi(int &x,int &y) {int t=x;x=y;y=t;}
void Faster(int x,int y) {if (distz[y]>distz[x]) swapi(que[x],que[y]);}
void Spfa()
{
    int j,k,MAX,x,headz=0,tailz=1;
    memset(distz,192,sizeof(distz));
    distz[st]=mo[st];que[tailz]=st;vis[st]=true;
    while (headz!=tailz)
    {
        headz=(headz+1)%maxn;x=que[headz];
        vis[x]=false;
        for (j=lnk[x][1];j;j=nxt[j][1])
            if (distz[x]+mo[son[j][1]]>distz[son[j][1]])
            {
                distz[son[j][1]]=distz[x]+mo[son[j][1]];
                if (!vis[son[j][1]])
                {
                    vis[son[j][1]]=true;
                    tailz=(tailz+1)%maxn;que[tailz]=son[j][1];
                    Faster((headz+1)%maxn,tailz);
                }
            }
    }
}
void add(int x,int y,int id) {son[++E[id]][id]=y;nxt[E[id]][id]=lnk[x][id];lnk[x][id]=E[id];}
int main()
{
    int i,j,x,y,fi,fj;
    freopen("1179.in","r",stdin);
    freopen("1179.out","w",stdout);
    readi(n);readi(m);
    for (i=1;i<=m;i++)
    {
        readi(x);readi(y);
        add(x,y,0);
    }
    for (i=1;i<=n;i++) readi(mo[i]);
    readi(st);readi(P);
    for (i=1;i<=P;i++) readi(who[i]);
    for (i=1;i<=n;i++) if (dfn[i]==0) Tarjan(i);
    for (i=1;i<=n;i++)
    {
        fi=father[i];
        for (j=lnk[i][0];j;j=nxt[j][0])
        {
            fj=father[son[j][0]];
            if (fi!=fj) add(fi,fj,1);
        }
    }
    st=father[st];
    for (i=1;i<=P;i++) who[i]=father[who[i]];
    Spfa();
    for (i=1;i<=P;i++) if (distz[who[i]]>ans) ans=distz[who[i]];
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值