POJ 3592 Instantaneous Transference

来源:互联网 发布:matlab数据拟合工具箱 编辑:程序博客网 时间:2024/05/16 14:10

题目大意:

        给出一个n*m的格子地图,每一格上面是0~9,“*”或“#”。如果格子上是数字代表这个格子上有当前数量的矿石。如果是“*” 代表着当前格子是一个传送阵可以传送到指定的地方。如果是“#”代表当前格子不可达。

        现在有一个矿车在坐标(0,0),也就是左上角。他只能向右和下行驶。当遇到传送阵时可以被传送到指定的位置。当他遇到数字时就可以得到那些数量的矿石,那个地方的矿石数量就变为“0”。问矿车最多可以采多少矿。


解题思路:

1、我们先要根据格子地图建图。(注1)

2、因为建立出的图可能会有环,我们要用Tarjan算法将环缩成点。(注2)

3、我们将缩点处理后的图重新建图。(注3)

4、对图求最长路。


注意:

1、要注意到“#”和从“#”出发的边是不建立的。当从“*”出发时需要建三条边:右,下,指定位置。

2、根据题意,经过的地方将不再有矿石。所以将环缩成点是最好的选择。因为如果可以到环中的任意一点,其他点也就可以到了。

3、重新建图的目的是为后来更容易的求最长路做准备。建图时对于每一条边(u,v),边的权值是点v所在的缩点的总权值。

4、求完最长路后得出的数值一定要再加上点0所在的缩点的总权值。

5、注意不要手残(手残毁一天啊~~~ T _ T ).


下面是代码:

#include <stdio.h>#include <string.h>#include <queue>using namespace std;const int MAXN = 2005;struct node{    int u,to,next;} edge[MAXN*10];struct node1{    int v,w,next;} newedge[MAXN*10];int n,m,p;int dfn[MAXN],low[MAXN],vis[MAXN],head[MAXN],stack1[MAXN],top,cnt,time;int num[MAXN],numcnt,numw[MAXN],map1[MAXN];int newhead[MAXN],newcnt;int dis[MAXN];char s[45][45];void init(){    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(vis,0,sizeof(vis));    memset(head,-1,sizeof(head));    memset(newhead,-1,sizeof(newhead));    memset(numw,0,sizeof(numw));    memset(stack1,-1,sizeof(stack1));    memset(num,-1,sizeof(num));    top=0;    cnt=0;    newcnt=0;    time=1;    numcnt=0;}int min(int a,int b){    if(a>b)a=b;    return a;}void addedge(int u,int v){    edge[cnt].u=u;    edge[cnt].to=v;    edge[cnt].next=head[u];    head[u]=cnt;    cnt++;}void Buildedge(){    int x,y;    for(int i=0; i<n; i++)    {        scanf("%s",s[i]);    }    for(int i=0; i<n; i++)    {        for(int j=0; j<m; j++)        {            if(s[i][j]=='*')            {                scanf("%d%d",&x,&y);                if(s[x][y]!='#')                    addedge(i*m+j,x*m+y);                map1[i*m+j]=0;                if(i+1<n&&s[i+1][j]!='#')                {                    addedge(i*m+j,(i+1)*m+j);                }                if(j+1<m&&s[i][j+1]!='#')                {                    addedge(i*m+j,i*m+j+1);                }            }            else if(s[i][j]!='#')            {                map1[i*m+j]=s[i][j]-'0';                if(i+1<n&&s[i+1][j]!='#')                {                    addedge(i*m+j,(i+1)*m+j);                }                if(j+1<m&&s[i][j+1]!='#')                {                    addedge(i*m+j,i*m+j+1);                }            }            else            {                map1[i*m+j]=0;            }        }    }}void dfs(int u,int fa){    dfn[u]=time;    low[u]=time;    time++;    vis[u]=1;    stack1[top]=u;    top++;    for(int i=head[u]; i!=-1; i=edge[i].next)    {        int v=edge[i].to;        if(!vis[v])        {            dfs(v,u);            low[u]=min(low[u],low[v]);        }        else if(vis[v]==1)        {            low[u]=min(low[u],dfn[v]);        }    }    if(low[u]==dfn[u])    {        while(stack1[top]!=u&&top>0)        {            top--;            num[stack1[top]]=numcnt;            vis[stack1[top]]=2;            numw[numcnt]+=map1[stack1[top]];        }        numcnt++;    }}void addedgenew(int u,int v){    for(int i=newhead[u]; i!=-1; i=newedge[i].next)    {        if(newedge[i].v==v)return;    }    newedge[newcnt].v=v;    newedge[newcnt].w=numw[v];    newedge[newcnt].next=newhead[u];    newhead[u]=newcnt;    newcnt++;}int spfa(int src){    queue <int> q;    q.push(src);    memset(vis,0,sizeof(vis));    vis[src]=true;    for(int i=0; i<=numcnt; i++)    {        dis[i]=-1;    }    dis[src]=0;    while(!q.empty())    {        int p,t=q.front();        q.pop();        p=newhead[t];        vis[t]=false;        while(p!=-1)        {            if(dis[newedge[p].v]<dis[t]+newedge[p].w)            {                dis[newedge[p].v]=dis[t]+newedge[p].w;                if(!vis[newedge[p].v])                {                    vis[newedge[p].v]=true;                    q.push(newedge[p].v);                }            }            p=newedge[p].next;        }    }    int max1=0;    for(int i=0; i<numcnt; i++)    {        if(dis[i]>max1)        {            max1=dis[i];        }    }    return max1+numw[src];}void Tarjan(){    for(int i=0; i<p; i++)    {        if(!vis[i])dfs(i,-1);    }}void BuildAgain(){    for(int i=0; i<p; i++)    {        for(int j=head[i]; j!=-1; j=edge[j].next)        {            if(num[i]!=num[edge[j].to]&&num[i]!=-1&&num[edge[j].to]!=-1)            {                addedgenew(num[i],num[edge[j].to]);            }        }    }}int main(){    int t;    scanf("%d",&t);    while(t--)    {        init();        scanf("%d%d",&n,&m);        Buildedge();//建图        p=n*m; //总点数        Tarjan();//求强连通分量用来缩点        BuildAgain();//重新建图        printf("%d\n", spfa(num[0]));//求最长路    }    return 0;}


0 0
原创粉丝点击