poj3592 Instantaneous Transference tarjan缩点+建图
2015-08-10 09:38
447 查看
//给一个n*m的地图,坦克从(0 , 0)开始走 //#表示墙不能走,*表示传送门可以传送到指定地方,可以选择也可以选择不传送 //数字表示该格的矿石数, //坦克从(0,0)开始走,只能往右和往下走, //问最多能得到多少矿石 //直接建图,但由于有传送门,需要缩点 //然后用dfs直接搜一条权值最大的路 #include<cstdio> #include<cstring> #include<iostream> #include<vector> #include<queue> using namespace std ; const int maxn = 2010 ; int dfn[maxn] , low[maxn] , vis[maxn] , stack[maxn] ;int ans ; int head[maxn*maxn] , belong[maxn] ,isstack[maxn] ; int num , top , nedge , step ;int X[maxn] , Y[maxn] ; int n, m ; int w[maxn];int a[maxn];int len;int visit[50][50]; int map[maxn][maxn] ;int pos ; char str[maxn][maxn] ; int dx[2] = {0,1} ; int dy[2] = {1,0} ; vector<int>vec[maxn] ; struct Edge { int v ; int next ; }edge[maxn*maxn] ; void addedge(int u , int v) { edge[nedge].v = v ; edge[nedge].next = head[u] ; head[u] = nedge++ ; } void init() { for(int i = 0;i <= n*m;i++) vec[i].clear() ; memset(head , -1 , sizeof(head)) ; memset(w ,0 , sizeof(w)) ; memset(dfn , 0 , sizeof(dfn)) ; memset(isstack ,0 , sizeof(isstack)) ; memset(map , 0 , sizeof(map)) ; memset(vis ,0 , sizeof(vis)) ; memset(a ,0 , sizeof(a)) ; num = top = nedge = step = len = 0 ; } void tarjan(int u) { stack[++top] = u ; isstack[u] = 1 ; low[u] = dfn[u] = ++step ; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v ; if(!dfn[v]) { tarjan(v) ; low[u] = min(low[u] , low[v]) ; } else if(isstack[v]) low[u] = min(low[u] , dfn[v]) ; } if(low[u] == dfn[u]) { num++ ; int v = -1 ; while(u != v) { v = stack[top--] ; isstack[v] = 0 ; belong[v] = num ; w[num] += a[v]; if(v==0)pos = num ; } } } void build_tree() { for(int i = 0;i <= n*m;i++) for(int j = head[i] ; j != -1 ; j =edge[j].next) { int u = belong[i] ; int v = belong[edge[j].v] ; if(u == v)continue ; vec[u].push_back(v) ; vis[v] = 1 ; } } int dfs(int u) { int ma = 0 ; for(int i = 0;i < vec[u].size() ;i++) { int v = vec[u][i] ; ma = max(ma , dfs(v)) ; } ans = max(ans , ma+w[u]) ; return ma + w[u] ; } int main() { //freopen("in.txt" , "r" , stdin) ; int t ; scanf("%d" , &t) ; while(t--) { scanf("%d%d" , &n , &m) ; init() ; ans = 0 ; for(int i = 0;i < n;i++) scanf("%s" ,str[i]) ; for(int i = 0;i < n;i++) { for(int j = 0;j < m;j++) if(str[i][j] != '#') { if(str[i][j] == '*') { X[++len] = i ; Y[len] = j ; a[i*m+j] = 0 ; } else { a[i*m + j] = str[i][j] - '0' ; ans = max(ans , a[i*m+j]) ; } for(int k = 0 ;k < 2;k++) { int nx = i + dx[k] ; int ny = j + dy[k] ; if((nx >= n || ny >= m)) addedge(i*m + j , n*m) ; else if(str[nx][ny] != '#') addedge(i*m + j , nx*m + ny) ; } } } for(int i = 1;i <= len ;i++) { int u , v ; scanf("%d%d" , &u , &v) ; addedge(X[i]*m+ Y[i] , u*m+v) ; } pos = 0 ; for(int i = 0;i <= n*m;i++) if(head[i] != -1 && !dfn[i]) tarjan(i) ; if(!pos) { cout<<ans<<endl; continue ; } build_tree() ; dfs(pos) ; printf("%d\n" ,ans) ; } }
相关文章推荐
- jQuery: 图片不完全按比例自动缩小
- 官网的shader stencilBuffer篇(续)
- javascript实现连续赋值
- JS 获取滚动条位置
- jQuery+css3实现Ajax点击后动态删除功能的方法
- js数值转换
- 关于ExtJS4.1创建Window拖动时会出现两个相同的Window
- javascript中间preventDefault与stopPropagation角色介绍
- jQuery图片上传前先在本地预览
- CSS3实现的一批hover特效
- js 浮动窗效果
- jQuery 判断所有图片加载完成
- js利用clipboardData在网页中实现截屏粘贴的功能
- 将网页中的html代码的table保存成word文件
- JavaScript高级程序设计笔记 事件冒泡和事件捕获
- Webix快速跨浏览器的JavaScript UI组件
- 判断浏览器是否支持 JS
- 发布 JavaScript 开源项目指南
- 发布 JavaScript 开源项目指南
- [转] javascript 获取滚动条高度+常用js页面宽度与高度