---
# System prepended metadata

title: Graph
tags: [Study_aboard]

---

# Graph 
###### tags: `Study_aboard`
## Find the celebrity ==Facebook==
![](https://i.imgur.com/cRgB8Tc.png)
![](https://i.imgur.com/z9V1TNb.png)

Sol1: We can represent the question as a graph 
Examples:

celeb is 1
![](https://i.imgur.com/Ojloi76.png)

No celeb
![](https://i.imgur.com/S7atsG8.png)

Brute force: To check if the node has no output edge and n input edge

```cpp 
bool knows(int a, int b);
class Solution {
public:
    int findCelebrity(int n) {
        vector<bool> candidate(n, true);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (candidate[i] && i != j) {
                    if (knows(i, j) || !knows(j, i)) {
                        candidate[i] = false;
                        break;
                    } else {
                        candidate[j] = false;
                    }
                }
            }
            if (candidate[i]) return i;
        }
        return -1;
    }
};
```

Sol2 ==better==

We can eliminate one member when we use know function
if know(a,b) return ```true```: we know that a cannot be the celebrity
if know(a,b) return ```false```: we know that b cannot be the celebrity

Therefore, we know that we can eliminate n-1 candidates by calling know function n-1 times, and we only need to check whether the last candidate is a celebrity

```cpp 
// Forward declaration of the knows API.
bool knows(int a, int b);

class Solution {
public:
    int findCelebrity(int n) {
        int res = 0;
        for (int i = 0; i < n; ++i) {
            if (knows(res, i)) res = i; 
            // if true, res cannot be celeb
            // if false, i cannot be celeb
        }
        for (int i = 0; i < n; ++i) {
            if (res != i && (knows(res, i) || !knows(i, res))) return -1;
        }
        return res;
    }
};
```

## Alien Dictionary ==Hard==
![](https://i.imgur.com/zFiPIBW.png)
![](https://i.imgur.com/2by1RLU.png)

Use topological sort

```cpp 
class Solution {
public:
    string alienOrder(vector<string>& words) {
        vector<vector<bool>> g(26, vector<bool>(26)); // DAG
        vector<bool> visited(26); // vector to record visited nodes, true = current path, false = already visited or have not visited yet
        string res;

        for (string word : words) {
            for (char c : word) {
                g[c - 'a'][c - 'a'] = true; // g[i][i] = true means that the char is used in the word
            }
        }

        for (int i = 0; i < (int)words.size() - 1; ++i) {
            int mn = min(words[i].size(), words[i + 1].size()), j = 0;
            for (; j < mn; ++j) {
                if (words[i][j] != words[i + 1][j]) {
                    g[words[i][j] - 'a'][words[i + 1][j] - 'a'] = true; // g[i][j]=true means that there is an edge from i to j
                    break;
                }
            }
            if (j == mn && words[i].size() > words[i + 1].size()) return ""; // invalid order
        }

        for (int i = 0; i < 26; ++i) { // dfs for every nodes (char) that are used
            if (!dfs(g, i, visited, res)) return "";
        }
        return res;
    }
    bool dfs(vector<vector<bool>>& g, int idx, vector<bool>& visited, string& res) { // return false when invalid
        if (!g[idx][idx]) return true; // idx is not used in all words
        visited[idx] = true;
        for (int i = 0; i < 26; ++i) {
            if (i == idx || !g[i][idx]) continue; // skip i=idx and skip when no edge from i to idx
            if (visited[i]) return false; // i is already visited -> invalid
            if (!dfs(g, i, visited, res)) return false; 
        }
        visited[idx] = false;
        g[idx][idx] = false;
        res += 'a' + idx;
        return true;
    }
};
```
