【BZOJ1179】atm,tarjan缩点+最长路径

来源:互联网 发布:淘宝详情页的制作 编辑:程序博客网 时间:2024/04/28 22:24

Time:2016.05.21
Author:xiaoyimi
转载注明出处谢谢


传送门
思路:
题目中是一个带点权的有向图,如果这是一个没有环的图那么问题就很简单,拓扑或者直接求最长(短)路径什么的信手拈来,但是它有环,这就要求我们对图进行重构,把它搞成一个有向无环图,然后求得极值路径就可以了
tarjan缩点重构图,然后在重构图上跑最长(短)路,最后的答案就是max(dis[有酒吧的点])
注意:
1.还是要注意,重构图和原图不能搞混了……
2.如果跑最长路的话,dis不要初始化为0,可能出现起点周围的点权都是0,直接导致从起点搜索一遍,没有点入队的情况
代码:

#include<bits/stdc++.h>using namespace std;#define M 500005int in(){    int t=0;char ch=getchar();    while (!isdigit(ch)) ch=getchar();    while (isdigit(ch)) t=(t<<1)+(t<<3)+ch-48,ch=getchar();    return t;}int n=in(),m=in(),s,p,tot,cnt;struct edge{int u,v,next;}e[M],E[M];int first[M],c[M],dfn[M],low[M],belong[M],First[M],C[M],dis[M];bool is_end[M],vis[M];stack<int>S;queue<int>Q;void add(int y,int x){e[++tot]=(edge){x,y,first[x]};first[x]=tot;}void Add(int x,int y){E[++tot]=(edge){x,y,First[x]};First[x]=tot;}void dfs(int x){    dfn[x]=low[x]=++cnt;    S.push(x);    vis[x]=1;    for (int i=first[x];i;i=e[i].next)        if (!dfn[e[i].v])            dfs(e[i].v),            low[x]=min(low[x],low[e[i].v]);        else if (vis[e[i].v])            low[x]=min(low[x],dfn[e[i].v]);    if (dfn[x]==low[x])    {        C[x]=0;        for (int y=-1;y!=x;y=S.top(),S.pop())            belong[S.top()]=x,            C[x]+=c[S.top()],            vis[S.top()]=0;    }}main(){    for (int i=1;i<=m;i++) add(in(),in());    for (int i=1;i<=n;i++) c[i]=in();    s=in();p=in();    for (int i=1;i<=p;i++) is_end[in()]=1;    tot=0;    for (int i=1;i<=n;i++)        if (!dfn[i]) dfs(i);    for (int i=1;i<=n;i++)        for (int j=first[i];j;j=e[j].next)            if (belong[i]!=belong[e[j].v])                Add(belong[i],belong[e[j].v]);    memset(dis,63,sizeof(dis));    Q.push(belong[s]);vis[belong[s]]=1;    dis[belong[s]]=-C[belong[s]];    while (!Q.empty())    {        int x=Q.front();        Q.pop();        vis[x]=0;        for (int i=First[x];i;i=E[i].next)            if (dis[x]-C[E[i].v]<dis[E[i].v])            {                dis[E[i].v]=dis[x]-C[E[i].v];                if (!vis[E[i].v]) Q.push(E[i].v),vis[E[i].v]=1;            }    }    int ans=0;    for (int i=1;i<=n;i++)        if (is_end[i]) ans=min(ans,dis[belong[i]]);    printf("%d",-ans);}
0 0
原创粉丝点击