Instantaneous Transference(强连通分量及其缩点)
http://poj.org/problem?id=3592
题意:给出一个n*m的矩阵,左上角代表起始点,每个格子都有一定价值的金矿,其中‘#’代表岩石不可达,‘*’代表时空门可以到达指定格子,求出可以获得的最大价值。
思路:时空门的存在可能会使得图中出现环,所以先对强连通分量进行缩点,然后对于缩点后的连通分量建立有向无环图,spfa求到起始点的最长路。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <queue>
#include <stack>
using namespace std;
const int N=;
const int INF=-<<;
struct node
{
int u,v,w;
int next;
} edge1[N*],edge2[N*];//edge1[]存的是原始图的边,edge2[]存的是缩点后的边
int low[N],dfn[N],sccno[N];//sccno[i]表示点i所属于的连通分量的编号
int dis[N],head1[N],head2[N],val[N];//val[]存储每个连通分量的价值
int n,m,scc_cnt,cnt,dfs_clock;
bool vis[N];
stack<int>S; void init()
{
cnt = ;
scc_cnt = ;
dfs_clock = ;
memset(val,,sizeof(val));
memset(low,,sizeof(low));
memset(dfn,,sizeof(dfn));
memset(sccno,,sizeof(sccno));
memset(head1,-,sizeof(head1));
memset(head2,-,sizeof(head2)); }
void add(int u,int v,int w,node *edge,int *head)
{
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void Tarjan(int u)//求强连通分量
{
low[u]=dfn[u]=++dfs_clock;
S.push(u);
for (int i = head1[u]; i!=-; i=edge1[i].next)
{
int v = edge1[i].v;
if (!dfn[v])
{
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if (!sccno[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if (low[u]==dfn[u])
{
++scc_cnt;
while()
{
int v = S.top();
S.pop();
sccno[v] = scc_cnt;
if (v==u)
break;
}
}
}
void spfa(int s)//求缩点后的最长路
{
for (int i = ; i <= n*m; i++)
{
dis[i]=INF;
vis[i]=false;
}
dis[s] = ;
queue<int>q;
q.push(s);
vis[s] = true;
while(!q.empty())
{
int u = q.front();
q.pop();
vis[u]=false;
for (int i = head2[u]; i!=-; i=edge2[i].next)
{
int v = edge2[i].v;
int w = edge2[i].w;
if (dis[v] < dis[u]+w)
{
dis[v] = dis[u]+w;
if (!vis[v])
{
q.push(v);
vis[v]=true;
}
} }
}
}
int main()
{
int t;
char map[][];
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(int i = ; i < n; i++)
{
scanf("%s",map[i]);
}
for (int i = ; i < n; i++)
{
for (int j = ; j < m; j++)
{
if (map[i][j]!='#')
{
if(i) add((i-)*m+j,i*m+j,,edge1,head1);
if(j) add(i*m+j-,i*m+j,,edge1,head1);
if (map[i][j]=='*')
{
int x,y;
scanf("%d%d",&x,&y);
if(map[x][y]!='#')
add(i*m+j,x*m+y,,edge1,head1);
}
}
}
}
for (int i = ; i < n; i++)
{
if (!dfn[i])
Tarjan(i);
}
for (int i = ; i < n; i++)
{
for (int j = ; j < m; j++)
{
if(map[i][j]!='*'&&map[i][j]!='#')
{
int num = sccno[i*m+j];
val[num]+=map[i][j]-'';//记录每个连通分量的价值
}
}
}
for (int u = ; u < n*m; u++)
{
for (int j = head1[u]; j!=-; j=edge1[j].next)
{
int v = edge1[j].v;
if(sccno[u]!=sccno[v])
{
add(sccno[u],sccno[v],val[sccno[v]],edge2,head2);
}//对缩点后的连通分量建立有向图
}
}
spfa(sccno[]);//求出每个点到起始点的价值
int max=-;
for (int i = ; i <= scc_cnt; i++)
{
if (max < dis[i])
max = dis[i];//求出到原点的最大价值
}
int ans = max+val[sccno[]];//总最大价值=到原点的最大价值+原点的价值
printf("%d\n",ans);
}
return ;
}
Instantaneous Transference(强连通分量及其缩点)的更多相关文章
- Tarjan求强连通分量,缩点,割点
Tarjan算法是由美国著名计算机专家发明的,其主要特点就是可以求强连通分量和缩点·割点. 而强联通分量便是在一个图中如果有一个子图,且这个子图中所有的点都可以相互到达,这个子图便是一个强连通分量,并 ...
- POJ-2186-Popular Cows(强连通分量,缩点)
链接:https://vjudge.net/problem/POJ-2186 题意: 有N(N<=10000)头牛,每头牛都想成为most poluler的牛,给出M(M<=50000)个 ...
- Tarjan算法求有向图强连通分量并缩点
// Tarjan算法求有向图强连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> #inc ...
- [HDOJ1827]Summer Holiday(强连通分量,缩点)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1827 缩点后统计入度和当前强连通分量中最小花费,然后记录入度为0的点的个数和花费和就行了. /* ━━ ...
- 强连通分量tarjan缩点——POJ2186 Popular Cows
这里的Tarjan是基于DFS,用于求有向图的强联通分量. 运用了一个点dfn时间戳和low的关系巧妙地判断出一个强联通分量,从而实现一次DFS即可求出所有的强联通分量. §有向图中, u可达v不一定 ...
- POJ3592 Instantaneous Transference 强连通+最长路
题目链接: id=3592">poj3592 题意: 给出一幅n X m的二维地图,每一个格子可能是矿区,障碍,或者传送点 用不同的字符表示: 有一辆矿车从地图的左上角(0,0)出发, ...
- POJ 1236 Network of Schools(强连通分量/Tarjan缩点)
传送门 Description A number of schools are connected to a computer network. Agreements have been develo ...
- [HDOJ4635]Strongly connected(强连通分量,缩点)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4635 题意:给一张图,问最多往这张图上加多少条边,使这张图仍然无法成为一个强连通图. 起初是先分析样例 ...
- [HDOJ5934]Bomb(强连通分量,缩点)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5934 题意:有n个炸弹,爆炸范围和点燃花费给你,如果一个爆炸那么它爆炸范围内的炸弹也会爆炸.问让所有炸 ...
随机推荐
- block教程
http://pernghh.pixnet.net/blog/trackback/eac87d412e/33563409 本文来自台湾的某开发人员的博客,被墙,感觉讲的比较易懂,所以引过来.文字简体化 ...
- 16监听器、Filter、Nginx、Spring、AOP
16监听器.Filter.Nginx.Spring.AOP-2018/07/30 1.监听器 监听web对象创建与销毁的监听器 ServletContextListener HttpSessionLi ...
- 暴力搜索+散列--P1008 三连击
题目描述 将1,2, ⋯,9共9个数分成3组,分别组成3个三位数,且使这3个三位数构成1:2:3的比例,试求出所有满足条件的3个三位数. 输入输出格式 输入格式: 木有输入 输出格式: 若干行,每行3 ...
- 洛谷——P3173 [HAOI2009]巧克力
P3173 [HAOI2009]巧克力 题目描述 有一块n*m的矩形巧克力,准备将它切成n*m块.巧克力上共有n-1条横线和m-1条竖线,你每次可以沿着其中的一条横线或竖线将巧克力切开,无论切割的长短 ...
- [luogu4056 JSOI2009] 火星藏宝图 (贪心 dp)
传送门 Solution 一个显然的贪心:选的点数越多越好.这个随便推推就知道了. 那么我们就贪心的从一列上挑最靠下的转移 直接转移不斜率优化复杂度\(O(nm)\),吸一口O2过了... Code ...
- Python学习——集合
集合 python中的集合和数学上集合具有基本相同的性质,此处不再赘述. 1.创建集合的两种方法 #直接创建 num={1,2,3,4,5} #利用set方法创建 num1=set([1,2,3,4, ...
- BZOJ 3747 洛谷 3582 [POI2015]Kinoman
[题解] 扫描线+线段树. 我们记第i部电影上次出现的位置是$pre[i]$,我们从$1$到$n$扫描,每次区间$(pre[i],i]$加上第i部电影的贡献$w[f[i]]$,区间$[pre[pre[ ...
- String HDU 5672(双指针)
String HDU 5672(双指针) 传送门 题意:一个字符串中找到所有拥有不少于k个不同的字符的子串. import java.io.*; import java.util.*; public ...
- BZOJ 3277 串 & BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析、启发式合并、线段树合并、主席树)
标签那么长是因为做法太多了... 题目链接: (bzoj 3277) https://www.lydsy.com/JudgeOnline/problem.php?id=3277 (bzoj 3473) ...
- UIColor用自定义颜色,TableView去掉背景色
1.用mac系统自带的数码测色计,选RGB模式,将值添加到ColorWithRed:xxx.0/255 最后的alpha选1.0 2.TableView的背景色要用setBackgroundView的 ...