People like People ZJU 2682 强联通+记忆化搜索

    技术2022-05-19  22

    题意:

     给定一个有向图.

     求一个最大的集合,是所有属于这个集合的点都满足以下条件:

    1.出度不为0

    2.指向的点都在这个集合内

    3.有属于这个集合的点指向这个点

    题解:

     我的做法是:对图缩点后,枚举每个点,以这个点作起点,并且这个点是由大于等于2个点缩点而得到的,然后这个点为根,以他能访问到的点构成树,如果所有叶子都是大于等于两个点以上缩点得到的,则说明该树构成一个合法的集合.取最大的合法集合即可.

    /*  * File:   main.cpp  * Author: swordholy  *  * Created on 2011年3月6日, 下午1:27  */ #include <cstdlib> #include <iostream> #include <memory.h> #include <stdio.h> #include<iostream> #include<vector> using namespace std; #define MY_MAX 100004 bool visited[MY_MAX], instack[MY_MAX]; int stack[MY_MAX], top; int N, M; vector<int> graph[MY_MAX]; vector<int> g[MY_MAX]; //rebuilded int dfn[MY_MAX], low[MY_MAX]; int color[MY_MAX], colorn[MY_MAX]; int INDEX, num, en; struct edge {     int x, y; }; edge e[MY_MAX]; int min(int x, int y) {     if (x < y) return x;     else return y; } void tarjan(int u) {     int v;     dfn[u] = low[u] = INDEX++;     stack[++top] = u;     instack[u] = true;     visited[u] = true;     for (size_t i = 0; i < graph[u].size(); ++i) {         v = graph[u][i];         if (!visited[v]) {             tarjan(v);             low[u] = min(low[u], low[v]);         } else if (instack[v])             low[u] = min(low[u], dfn[v]);     }     if (dfn[u] == low[u]) {         ++num;         color[u] = num;         do {             v = stack[top--];             color[v] = num;             instack[v] = false;         } while (v != u);     } } int d[100005]; int dfs(int x) {     int i, j, sum;     if (d[x] != -1) return d[x];     d[x] = 0;     if ((g[x].size() == 0)) {         if (colorn[x] >= 2) {d[x]=colorn[x];return colorn[x];}         else return 0;     }     sum = colorn[x];     for (i = 0; i < g[x].size(); i++) {         int temp = dfs(g[x][i]);         if (temp == 0) return 0;         sum += temp;     }     d[x] = sum;     return sum; } /*  */ int main(int argc, char** argv) {     int n, i, j, t, u, m, vv, id, idn, v[5];     cin >> t;     for (u = 1; u <= t; u++) {         scanf("%d %d", &n, &m);         for (i = 1; i <= n; i++)             graph[i].clear();         en = 0;         for (vv = 1; vv <= m; vv++) {             scanf("%d %d", &id, &idn);             for (i = 1; i <= idn; i++) {                 scanf("%d", &v[i]);                 graph[id].push_back(v[i]);                 ++en;                 e[en].x = id;                 e[en].y = v[i];             }         }    /*     for(i=1;i<=5;i++)         {             for(j=0;j<graph[i].size();j++)                 printf("%d ",graph[i][j]);         printf("/n");         }*/         ///         //init....         top = 0;         num = 0;         INDEX = 1;         memset(visited, 0, sizeof (visited));         memset(instack, 0, sizeof (instack));         //         //calc color by tarjan         for (i = 1; i <= n; i++)             if (!visited[i]) tarjan(i);         //         //rebuild a map         for (i = 1; i <= n; i++)             g[i].clear();         for (i = 1; i <= en; i++)             if (color[e[i].x] != color[e[i].y])                 //不能自己指向自己                 g[color[e[i].x]].push_back(color[e[i].y]);         ///         memset(colorn, 0, sizeof (colorn));         for (i = 1; i <= n; i++)             colorn[color[i]]++;         bool fl = true;         memset(d, -1, sizeof (d));         int ans = 0;         for (i = 1; i <= num; i++)             if (colorn[i] >= 2) {                 int v = dfs(i);                 if (v > ans) ans = v;             }         printf("%d/n", ans);     }     return 0; }


    最新回复(0)