5月27日-图-题解
1791. 找出星型图的中心节点
解法1.
计算每个点的度,判断度是否到了n-1
,n为点的个数
int findCenter(vector<vector<int>>& edges) {
int n=edges.size()+1;
int point[n+1];
memset(point,0,sizeof(point));
for(int i=0;i<n-1;++i){
if(++point[edges[i][0]]==n-1){
return edges[i][0];
}
if(++point[edges[i][1]]==n-1){
return edges[i][1];
}
}
return 0;
}
解法2.
因为中心点必与其余点连接,只需要随便取两对边,判断其中重合的点即为中心点
int findCenter(vector<vector<int>>& edges) {
int k=edges[0][0];
if(k==edges[1][0]||k==edges[1][1]){
return k;
}
return edges[0][1];
}
797. 所有可能的路径
简单的回溯一下,记录每个走过的节点即可
List<List<Integer>> ans;
int n;
List<Integer> path;
// index 为当前到达的节点
void backTracking(int[][] graph, int index) {
if (index == n) {
ans.add(new ArrayList<>(path));
return;
}
int[] next = graph[index];
for (int i = 0; i < next.length; ++i) {
path.add(next[i]);
backTracking(graph, next[i]);
path.remove(path.size() - 1);
}
}
public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
n = graph.length - 1;
ans = new ArrayList<>();
path = new ArrayList<>();
path.add(0);
backTracking(graph, 0);
return ans;
}
851. 喧闹和富有
建立反图,对于people X,把所有比X富有的人放一起,进行DFS,这里注意要用到一个hash[u]
,作用如下
我们假设 1比2富有,3比2富有,而1比3富有,那么我们在计算DFS(3)的时候已经计算过1了,这里就无需重复计算避免超时,所以设定一个hash数组来终止遍历
vector<int> edges[510];
int hash[501];
void dfs(vector<int>& quiet,int u,int &ans){
if(hash[u]){
return;
}
hash[u]=1;
if(quiet[u]<quiet[ans]){
ans=u;
}
for(int i=0;i<edges[u].size();++i){
int v=edges[u][i];
dfs(quiet,v,ans);
}
}
public:
vector<int> loudAndRich(vector<vector<int>>& richer, vector<int>& quiet) {
int n=quiet.size();
for(int i=0;i<n;++i){
edges[i].clear();
}
for(int i=0;i<richer.size();++i){
edges[richer[i][1]].push_back(richer[i][0]);
}
vector<int> ret;
for(int i=0;i<n;++i){
memset(hash,0,sizeof(hash));
int ans=i;
dfs(quiet,i,ans);
ret.push_back(ans);
}
return ret;
}
959. 由斜杠划分区域
用到并查集思路,为什么英雄哥的做法里要将一个方块再分为四个呢,就是为了方便统计连通情况,这里盗下英雄哥的图予以说明
对于每个小方块来说,因为要考虑和其他方块的连通情况,所以要进行划分,并有如下几种类型
区域3:不管字符是什么,都会与正下方方块的区域0连通
区域2:不管字符是什么,都会与正右方方块的区域1连通
“/”:区域0,1连通,2,3连通
“\”:区域0,2连通,1,3连通
”空字符“:0,1,2,3均连通
最终,在构造出节点之间的连接关系后,就可以利用并查集求出连通分量的数目了。利用一个hash统计结果即可
代码中的划分是按照顺时针0,1,2,3划分的,注意区别
class Solution {
#define maxn 4000
int f[maxn];
void init(){
for (int i = 0; i <maxn; i++) {
f[i] = i;
}
}
int find(int x) {
return x == f[x] ? (x) : (f[x] = find(f[x]));
}
bool merge(int x, int y) {
int fx = find(x), fy = find(y);
if (fx != fy) {
f[fx] = fy;
return true;
}
return false;
}
public:
int regionsBySlashes(vector<string>& grid) {
int n = grid.size();
init();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int idx = i * n + j;
if (i < n - 1) {
int bottom = idx + n;
merge(idx * 4 + 2, bottom * 4);
}
if (j < n - 1) {
int right = idx + 1;
merge(idx * 4 + 1, right * 4 + 3);
}
if (grid[i][j] == '/') {
merge(idx * 4, idx * 4 + 3);
merge(idx * 4 + 1, idx * 4 + 2);
} else if (grid[i][j] == '\\') {
merge(idx * 4, idx * 4 + 1);
merge(idx * 4 + 2, idx * 4 + 3);
} else {
merge(idx * 4, idx * 4 + 1);
merge(idx * 4 + 1, idx * 4 + 2);
merge(idx * 4 + 2, idx * 4 + 3);
}
}
}
int hash[n*n*4];
int cnt=0;
memset(hash,0,sizeof(hash));
for (int i = 0; i < n * n * 4; i++) {
int fa = find(i);
if(!hash[fa]){
hash[fa]=1;
++cnt;
}
}
return cnt;
}
};