poj3592 有向有环图最长路

来源:互联网 发布:大型数据机房制冷系统 编辑:程序博客网 时间:2024/05/21 12:39

题意:有向有环图,求最长路(每个点权值仅算一次)

做法:1.scc缩点,建立scc图 2.求scc图最长路(spfa)

#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>#include<map>#include<vector>#include<queue>#include<stack>#define ll long long#define sf scanf#define pf printf#define maxn 50*50#define INF 0x3f3f3f3f#define mem(a,b) memset(a,b,sizeof(a))#define lowbit(x) x&(-x)const ll mod=1000000007;using namespace std;int t,n,m;char ma[maxn][maxn];int ore[maxn];stack<int> S;vector<int> sccg[maxn];int d[maxn];struct Edge{    int to,next;}edge[maxn*maxn];int head[maxn],tot,scc_cnt,dfs_clock,pre[maxn],low[maxn],sccno[maxn],sum[maxn];void add(int u,int v){    edge[tot].to=v,edge[tot].next=head[u],head[u]=tot++;}void dfs(int u){    pre[u]=low[u]=++dfs_clock;    S.push(u);    for(int i=head[u];i!=-1;i=edge[i].next){        int v=edge[i].to;        if(!pre[v]) { dfs(v);low[u]=min(low[u],low[v]); }        else if(!sccno[v]) low[u]=min(low[u],pre[v]);    }    if(pre[u]==low[u]){        scc_cnt++;        for(;;){            int x=S.top();S.pop();            sccno[x]=scc_cnt;            sum[scc_cnt]+=ore[x];            if(x==u) break;        }    }}void find_scc(){    mem(pre,0),mem(sccno,0),mem(sum,0),dfs_clock=scc_cnt=0;    for(int i=0;i<m*n;i++) if(!pre[i]) dfs(i);}void build_scc(){    for(int i=0;i<=scc_cnt;i++) sccg[i].clear();    for(int u=0;u<m*n;u++){        for(int i=head[u];i!=-1;i=edge[i].next){            int v=edge[i].to;            if(sccno[u]!=sccno[v]) sccg[sccno[u]].push_back(sccno[v]);        }    }}void spfa_long(){    queue<int> q;    bool inq[maxn]; mem(inq,0);    for(int i=1;i<=scc_cnt;i++) d[i]=((sccno[0]==i)?sum[i]:0);    q.push(sccno[0]);    while(!q.empty()){        int u=q.front();q.pop();        inq[u]=false;        for(int i=0;i<sccg[u].size();i++){            int v=sccg[u][i];            if(d[v]<d[u]+sum[v]) d[v]=d[u]+sum[v];            if(!inq[v]){                inq[v]=true;                q.push(v);            }        }    }}int main(){    //freopen("a.txt","r",stdin);    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        for(int i=0;i<n;i++) scanf("%s",ma[i]);        mem(ore,0),mem(head,-1),tot=0;        for(int i=0;i<n;i++)            for(int j=0;j<m;j++){                if(ma[i][j]!='#'){                    if(i+1<n&&ma[i+1][j]!='#') add(i*m+j,(i+1)*m+j);                    if(j+1<m&&ma[i][j+1]!='#') add(i*m+j,i*m+j+1);                    if(ma[i][j]=='*'){                        int a,b;scanf("%d%d",&a,&b);                        if(ma[a][b]!='#') add(i*m+j,a*m+b);                        ore[i*m+j]=0;                    }                    else ore[i*m+j]=ma[i][j]-'0';                }            }        find_scc();        build_scc();        spfa_long();        int ans=0;        for(int i=1;i<=scc_cnt;i++) ans=max(d[i],ans);        printf("%d\n",ans);    }}


0 0