poj 3160 强连通+最长路

来源:互联网 发布:飘零网络验证金盾 编辑:程序博客网 时间:2024/06/14 08:26

题意:

给定n个点 m条有向边的图 ,每个点的点权。

问:

遍历一遍图能得到的最大点权(对于经过的点,可以选择是否获得该点点权,但每个点只能被获得一次)。起点可以任意。

先将整个图缩点,然后建立一个超级源点,再跑一边最长路就好了。(最长路最好用spfa,队列优化dij超时,我试是这样)

#include<stdio.h>#include<string.h>#include<stack>#include<queue>#include<algorithm>using namespace std;#define ll long long#define me(a,b) memset(a,b,sizeof(a))struct node{    int u,v,next;}e[16000];struct node1{    int u,v,next;}e2[16000];struct node2{    int u,len;    bool operator  <(const node2& a)const    {        return len<a.len;    }}g[200000];int n,m;int head[3000],head2[3000],top,top2,cnt,tot,dfn[3000],low[3000],scnt[3000],val[3000],dis[3000],book[3000],val1[3000];void add(int u,int v){    e[top].u=v;    e[top].v=u;    e[top].next=head[u];    head[u]=top++;}void add2(int u,int v){    e2[top2].u=v;    e2[top2].v=u;    e2[top2].next=head2[u];    head2[u]=top2++;}stack<int>q;void tarjan(int x){    dfn[x]=low[x]=++tot;    q.push(x);    for(int i=head[x];i!=-1;i=e[i].next)    {        int u=e[i].u;        if(!dfn[u])        {            tarjan(u);            low[x]=min(low[u],low[x]);        }        else if(!scnt[u])        {            low[x]=min(dfn[u],low[x]);        }    }    if(low[x]==dfn[x])    {        int v=-1;        cnt++;        while(v!=x)        {            v=q.top();            q.pop();            scnt[v]=cnt;        }    }}void spfa(){    me(book,0);    me(dis,0);    me(val1,0);    //printf("%d %d\n",scnt[1],scnt[0]);    for(int i=0;i<n;i++)    {        val1[scnt[i]]+=(val[i]>0?val[i]:0);    }    //printf("%d...\n",val1[1]);    queue<int>p;    p.push(0);    while(!p.empty())    {        int f=p.front();        p.pop();        book[f]=0;        for(int i=head2[f];i!=-1;i=e2[i].next)        {            int u=e2[i].u;            if(dis[u]<dis[f]+val1[u])            {                dis[u]=dis[f]+val1[u];                if(!book[u])                    p.push(u);            }        }    }    int max1=0;    for(int i=1;i<=cnt;i++)    {        max1=max(max1,dis[i]);    }    printf("%d\n",max1);}int main(){    while(~scanf("%d%d",&n,&m))    {        me(head,-1);        me(dfn,0);        me(low,0);        me(scnt,0);        me(head2,-1);        top=tot=cnt=top2=0;        for(int i=0;i<n;i++)            scanf("%d",&val[i]);        for(int i=0;i<m;i++)        {            int a,b;            scanf("%d%d",&a,&b);            add(a,b);        }        for(int i=1;i<n;i++)        {            if(!dfn[i])            tarjan(i);        }        for(int i=0;i<top;i++)        {            int u=e[i].u;            int v=e[i].v;            if(scnt[u]!=scnt[v])            {                add2(scnt[v],scnt[u]);            }        }        for(int i=1;i<=cnt;i++)        {            add2(0,i);        }        spfa();    }}

阅读全文
1 0
原创粉丝点击