POJ3592 Instantaneous Transference 强连通+最长路
题目链接:
题意:
给出一幅n X m的二维地图,每一个格子可能是矿区,障碍,或者传送点 用不同的字符表示;
有一辆矿车从地图的左上角(0,0)出发,仅仅能往右走或往下走,或者通过传送点 选择是否 传送到特定地点
採过的矿的格子 矿会消失;问这辆矿车最多能採多少矿
解题思路:
首先又一次建图,将图中二维的顶点压缩成一维的顶点 (方便Tarjan算法)
每一个顶点往右,下的顶点建边,传送点的格子往特定顶点建边(建边的两端不能有障碍)
得到一幅可能存在环的有向图;
由于採过矿的格子不能够二次採矿,所以经过某个环等于採集了整个环中全部的矿
我们用Tarjan算法缩点 再又一次建图
得到一幅无环有向图,而图中每条边(u->v)的权值应等于value[v]
最后再用spfa求这幅图的最长路就可以
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 1650
using namespace std;
struct node
{
int to,next,w;
} edge1[maxn*3],edge2[maxn*3];
int head1[maxn],head2[maxn];
int s1,s2; int dfn[maxn], low[maxn],num; int sta[maxn],insta[maxn], top; int belong[maxn],block; int n,m,ss,v1[maxn],v2[maxn];
char map[45][45]; void init()
{
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
memset(dfn,0,sizeof(dfn));
memset(insta,0,sizeof(insta));
memset(belong,0,sizeof(belong));
memset(v2,0,sizeof(v2));
s1=s2=num=top=block=0;
} int judge(int x,int y)
{
if(x<0||y<0||x>=n||y>=m)
return -1;
if(map[x][y]>='0'&&map[x][y]<='9')
return 1;
if(map[x][y]=='*')
return 2;
if(map[x][y]=='#')
return -1;
} void addedge(int d,int u,int v,int w)
{
if(d==1){
edge1[s1]={v,head1[u]};
head1[u]=s1++;
}
else {
edge2[s2]={v,head2[u],w};
head2[u]=s2++;
}
} void Tarjan(int u,int pre)
{
dfn[u]=low[u]=++num;
insta[u]=1;
sta[top++]=u;
for(int i=head1[u];i!=-1;i=edge1[i].next)
{
int v=edge1[i].to;
if(!dfn[v])
{
Tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else if(insta[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]) //缩点
{
block++;
int d=-1;
while(d!=u)
{
d=sta[--top];
insta[d]=0;
belong[d]=block;
v2[block]+=v1[d];
}
}
} void rebuild()
{
int u,v;
for(int i=0;i<n*m;i++)
{
u=belong[i];
for(int j=head1[i];j!=-1;j=edge1[j].next)
{
v=edge1[j].to;
v=belong[v];
if(u!=v) //又一次建边
addedge(2,u,v,v2[v]);
}
}
} void spfa()
{
int u,v,start=belong[0]; //起点为(0,0)所在的强连通分量里面
queue<int>q;
int vis[maxn]={0};
int dis[maxn]={0};
vis[start]=1;
dis[start]=v2[start];
q.push(start);
while(!q.empty())
{
u=q.front();
q.pop();
vis[u]=0;
for(int i=head2[u];i!=-1;i=edge2[i].next)
{
v=edge2[i].to;
if(dis[v]<dis[u]+edge2[i].w)
{
dis[v]=dis[u]+edge2[i].w;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
int ans=0;
for(int i=1;i<=block;i++)
if(dis[i]>ans)
ans=dis[i];
cout<<ans<<endl; } int main()
{
int T,s,ss,loc;
char ch;
int pos[maxn][2];
scanf("%d",&T);
while(T--)
{
s=1,ss=0;
init();
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
cin>>map[i][j];
if(map[i][j]=='*')
ss++;
}
for(int i=1; i<=ss; i++) //记录第i个传送点的传送位置
scanf("%d%d",&pos[i][0],&pos[i][1]); for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
loc=i*m+j; //一维顶点
if(judge(i,j)==1)
v1[loc]=map[i][j]-'0';
else if(judge(i,j)==2)
v1[loc]=0; //传送点没有矿
if(judge(i,j)!=-1)
{
if(judge(i+1,j)!=-1) //下
addedge(1,loc,loc+m,0);
if(judge(i,j+1)!=-1) //右
addedge(1,loc,loc+1,0);
if(judge(i,j)==2) //传送点
addedge(1,loc,pos[s][0]*m+pos[s++][1],0);
}
else
v1[loc]=-1; //障碍
} for(int i=0;i<n*m;i++)
if(!dfn[i]&&v1[i]!=-1) //注意障碍不能进行Tarjan
Tarjan(i,-1);
rebuild();
spfa();
}
return 0;
}
POJ3592 Instantaneous Transference 强连通+最长路的更多相关文章
- POJ3592 Instantaneous Transference题解
题意: 给一个矩形,矩形中某些点有一定数量的矿石,有些点为传送点,有些点为障碍.你驾驶采矿车(ore-miner truck,我也不知道是什么),从左上角出发,采尽量多的矿石,矿石不可再生.不能往左边 ...
- Instantaneous Transference(强连通分量及其缩点)
http://poj.org/problem?id=3592 题意:给出一个n*m的矩阵,左上角代表起始点,每个格子都有一定价值的金矿,其中‘#’代表岩石不可达,‘*’代表时空门可以到达指定格子,求出 ...
- POJ3592 Instantaneous Transference tarjan +spfa
链接:http://poj.org/problem?id=3592 题意:题目大意:给定一个矩阵,西南角为出发点,每个单位都有一订价值的金矿(#默示岩石,不成达,*默示时佛门,可以达到指定单位),队# ...
- poj3592 Instantaneous Transference tarjan缩点+建图
//给一个n*m的地图.坦克从(0 , 0)開始走 //#表示墙不能走,*表示传送门能够传送到指定地方,能够选择也能够选择不传送 //数字表示该格的矿石数, //坦克从(0,0)開始走.仅仅能往右和往 ...
- poj 3592 Instantaneous Transference 缩点+最长路
题目链接 给一个n*m的图, 从0, 0这个点开始走,只能向右和向下. 图中有的格子有值, 求能获得的最大值. 其中有些格子可以传送到另外的格子, 有些格子不可以走. 将图中的每一个格子都看成一个点, ...
- POJ 3592--Instantaneous Transference【SCC缩点新建图 && SPFA求最长路 && 经典】
Instantaneous Transference Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 6177 Accep ...
- UVA11324 The Largest Clique (强连通缩点+DP最长路)
<题目链接> 题目大意: 给你一张有向图 G,求一个结点数最大的结点集,使得该结点集中的任意两个结点 u 和 v 满足:要么 u 可以达 v,要么 v 可以达 u(u,v相互可达也行). ...
- ZOJ 3795 Grouping (强连通缩点+DP最长路)
<题目链接> 题目大意: n个人,m条关系,每条关系a >= b,说明a,b之间是可比较的,如果还有b >= c,则说明b,c之间,a,c之间都是可以比较的.问至少需要多少个集 ...
- The Largest Clique UVA - 11324( 强连通分量 + dp最长路)
这题 我刚开始想的是 缩点后 求出入度和出度为0 的点 然后统计个数 用总个数 减去 然而 这样是不可以的 画个图就明白了... 如果 减去度为0的点 那么最后如果出现这样的情况是不可 ...
随机推荐
- java web开发基础实例(javabean+jsp+servlet+jdbc)
JavaBean:用于传递数据,拥有与数据相关的逻辑处理 JSP:从Model接收数据并生成HTML Servlet:接收HTTP请求并控制Model和View jdbc:用于配置环境 一.[建立数据 ...
- Django Model one
models :URL---->http://www.cnblogs.com/wupeiqi/p/6216618.html null 数据库中字段是否可以 ...
- Vmware复制完好的linux目录后网卡操作
目录 Vmware复制完好的linux目录后网卡操作 修改/etc/udev/rules.d/70-persistent-net.rules 修改网卡配置文件 重启查看 Vmware复制完好的linu ...
- Leetcode7--->Reverse Integer(逆转整数)
题目: 给定一个整数,求将该整数逆转之后的值: 举例: Example1: x = 123, return 321Example2: x = -123, return -321 解题思路: 在这里只用 ...
- 下载,配置环境变量,第一个demo
一.在 http://www.oracle.com 下载java JDK 安装到自定义的地方. 二.配置环境变量:在我的电脑→高级系统设置→环境变量 ① 找到Path新增一个路径(该路径为JDK存放的 ...
- SpriteKit-SKView
1.暂停这个视图 @property (nonatomic, getter = isPaused) BOOL paused; 2.视图性能的一些参数 @property (nonatomic) BOO ...
- BZOJ 4552 [Tjoi2016&Heoi2016]排序 ——线段树 二分答案
听说是BC原题. 好题,二分答案变成01序列,就可以方便的用线段树维护了. 然后就是区间查询和覆盖了. #include <map> #include <cmath> #inc ...
- 刷题总结——分配笔名(51nod1526 trie树)
题目: 班里有n个同学.老师为他们选了n个笔名.现在要把这些笔名分配给每一个同学,每一个同学分配到一个笔名,每一个笔名必须分配给某个同学.现在定义笔名和真名之间的相关度是他们之间的最长公共前缀.设笔名 ...
- linux JDK安装(一)
1.先卸载服务器自带的jdk软件包# java -version #查看服务器是否安装过jdkjava version "1.6.0_17"OpenJDK Runtime Envi ...
- 切糕(bzoj 3144)
Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x, ...