tarjan,dfs

题意:

图片说明

分析:

不知道怎么回事,这道题做的时候总是有点迷迷糊糊的,犯了好多低级错误。。。。。。

总之,如果接触到tarjan的话那么我们肯定能够反映过来:一定要缩点的。
缩点后啊,这张图就是一张拓扑图。有向无环。每割点都有权值,就是此节点缩的点数
那现在让我们从这张有向无环图中找一条路径,是这个路径的点权和最大!!

很简单啦,因为是有向无环图。所以我们可以对每一个点直接dfs。

int res[max_n];
int dfs(int u) {
    if (res[u] != 0)return res[u];
    for (int i = head2[u];i;i = E2[i].next) {
        int v = E2[i].to;
        res[u] = max(res[u], dfs(v));
    }res[u] += cs[u];
    return res[u];
}
int ans = 0;
    for (int i = 1;i <= colour;i++)
        ans = max(ans, dfs(i));

注意,记忆化搜索,否则tle

主要麻烦的事,对输入数据的处理。肯定是不能把矩形直接画出来的。太大了。

另外对于横天门和纵寰门,如果乖乖的连边的话肯定会爆炸!
所以我们可以这样做,对于第一个x行的横天们,我们把他与该行中每一个宫殿连上,
剩下的该行的横天门,我们都和第一个横天门链接就好了。

纵寰门也是如此!

那么***,我们就老老实实的连就好了。

注意地是,并不是所有的格子都有宫殿的,这是个相当稀疏的矩阵。我们用map进行处理。

代码如下:

#include<iostream>
#include<algorithm>
#include<stack>
#include<vector>
#include<map>
using namespace std;
typedef pair<int, int> pii;
const int max_n = 1e5 + 100;
const int max_m = 12 * max_n;
int rr[max_n], cc[max_n];
int n, r, c;

struct edge{
    int to, next;
}E[max_m];
int head[max_n];
int cnt = 1;
void add(int from, int to) {
    E[cnt].to = to;
    E[cnt].next = head[from];
    head[from] = cnt++;
}

edge E2[max_m];
int head2[max_n];
int cnt2 = 1;
void add2(int from, int to) {
    E2[cnt2].to = to;
    E2[cnt2].next = head2[from];
    head2[from] = cnt2++;
}

int dfn[max_n], low[max_n], color[max_n];
int colour = 0, tot = 0;
int cs[max_n];
stack<int> st;
void tarjan(int u) {
    dfn[u] = low[u] = ++tot;st.push(u);
    for (int i = head[u];i;i = E[i].next) {
        int v = E[i].to;
        if (!dfn[v]) { tarjan(v);low[u] = min(low[u], low[v]); }
        else if (color[v] == 0)low[u] = min(low[u], dfn[v]);
    }if (low[u] != dfn[u])return;
    color[u] = ++colour;cs[colour]++;
    while (st.top() != u) {
        color[st.top()] = colour;
        st.pop();
        cs[colour]++;
    }st.pop();
}

int res[max_n];
int dfs(int u) {
    if (res[u] != 0)return res[u];
    for (int i = head2[u];i;i = E2[i].next) {
        int v = E2[i].to;
        res[u] = max(res[u], dfs(v));
    }res[u] += cs[u];
    return res[u];
}

struct node{
    int x, y, t;
};
map<pii, int> mp;
node input[max_n];
vector<int> rrt[max_n];
vector<int>cct[max_n];
int main() {
    ios::sync_with_stdio(0);
    cin >> n >> r >> c;
    for (int i = 1;i <= n;i++) {
        cin >> input[i].x >> input[i].y >> input[i].t;
        mp[{input[i].x, input[i].y}] = i;
        rrt[input[i].x].push_back(i);
        cct[input[i].y].push_back(i);
    }
    for (int i = 1;i <= n;i++) {
        int x = input[i].x, y = input[i].y, t = input[i].t;
        int num = mp[{x,y}];
        if (t == 1) {
            if (rr[x] != 0)add(num, rr[x]);
            else {
                for (int j : rrt[x])
                    if (j == num)continue;
                    else add(num, j);
                rr[x] = num;
            }
        }
        else if (t == 2) {
            if (cc[y] != 0)add(num, cc[y]);
            else {
                for (int j : cct[y])
                    if (j == num)continue;
                    else add(num, j);
                cc[y] = num;
            }
        }
        else {
            for (int j = x-1;j <= x+1;j++) {
                for (int k = y-1;k <= y+1;k++) {
                    if ((j == x && k == y) || !mp[{ j,k }])continue;
                    if (j <= r && j >= 1 && k <= c && k >= 1)
                        add(num, mp[{j, k}]);
                }
            }
        }
    }
    for (int i = 1;i <= n;i++)
        if (!dfn[i])tarjan(i);
    for (int i = 1;i <= n;i++) {
        for (int j = head[i];j;j = E[j].next) {
            int v = E[j].to;
            if (color[v] == color[i])continue;
            else add2(color[i], color[v]);
        }
    }int ans = 0;
    for (int i = 1;i <= colour;i++)
        ans = max(ans, dfs(i));
    cout << ans << endl;
}