• luogu解题报告:P1262间谍网络【代码量惊人】【图论/强连通缩点】


    题目见https://www.luogu.org/problem/show?pid=1262

    分析

    这个题一眼看上去并不难,似乎bfs就能解决问题,但事实上bfs只能解决第一问。第二问如何解决呢?首先要明确:强连通分量内如果有一个间谍被捕,所有人就会被捕,代价是其中所需金额最少的一个。因此可以进行强连通缩点,变成一个DAG。不难发现,金额最少就是DAG中所有入度为0的点的金额和。因为这些点非取不可,且取了就可以控制所有人。
    然后就开始考验码农功了。。。。。对象的思想得到了运用。。

    示例代码

    #include <bits/stdc++.h>
    using namespace std;
    
    //#define DEBUG
    
    /*basis of graph*/
    class graph {
    public:
            struct p {
                    int to, next;
            } edge[9005];
            int head[3003], top;
            int rank[3003];
            int rd[3003];
            graph() 
            {
                    memset(head, 0, sizeof head);
                    memset(rd, 0, sizeof rd);
                    memset(rank, 127/3, sizeof rank);
                    top = 0;
            }
            void edit_rank(int i, int j)
            {
                    rank[i] = j;
            }
            void push(int i, int j)
            {
                    edge[++top].to = j;
                    edge[top].next = head[i];
                    head[i] = top;
                    rd[j]++;
            }
    };
    
    /* vars */
    graph basic, reversed, solved;
    int n, p, r;
    int grp = 0;
    
    /*kosaraju algorithm*/
    int dfn[3005], t = 0, visited[3005], rank_g[3005];
    int hash_tab[3005][3005];
    void get_dfn(int i)
    {
            if (!visited[i]) {
                    visited[i] = 1;
                    for (int k = basic.head[i]; k; k = basic.edge[k].next) 
                            get_dfn(basic.edge[k].to);
                    dfn[++t] = i;
            }
    }
    void dfs(int i, int group)
    {
            #ifdef DEBUG
            cout << "DEBUG DFS CALLED i = " << i << " ; group = " << group << endl;
            #endif
            visited[i] = group;
            rank_g[group] = min(rank_g[group], basic.rank[i]);
            for (int k = reversed.head[i]; k; k = reversed.edge[k].next)
                    if (!visited[reversed.edge[k].to])
                            dfs(reversed.edge[k].to, group);
    }
    
    /*work functions*/
    
    // using by function::able & funcion::work
    queue<int> que;
    bool killed[3005];
    
    bool able()
    {
            int count = 0;
            for (int i = 1; i <= n; i++)
                    if (basic.rank[i] <= 233333333) {
                            que.push(i);
                            killed[i] = 1;
                    }
            while (!que.empty()) {
                    int i = que.front(); 
                    que.pop();
                    count++;
                    for (int k = basic.head[i]; k; k = basic.edge[k].next) {
                            int to = basic.edge[k].to;
                            if (!killed[to]) {
                                    killed[to] = 1;
                                    que.push(to);
                            }
                    }
            }
            return count == n;
    }
    
    void view(const graph &g)
    {
            cout << "VIEWING GRAPH......" << endl;
            int k;
            cin >> k;
            for (int i = 1; i <= n; i++) {
                    if (g.head[i])
                            cout << "." << i << endl;
                    for (int k = g.head[i]; k; k = g.edge[i].next)
                            cout << "--	" << g.edge[k].to << endl;
            }
            cout << "Finish." << endl;
    }
    
    void work()
    {
            #ifdef DEBUG
            view(basic);
            view(solved);
            #endif
            if (!able()) {
                    cout << "NO" << endl;
                    for (int i = 1; i <= n; i++)
                            if (!killed[i]) {
                                    cout << i << endl;
                                    return;
                            }
            } 
            int ans = 0;
            for (int i = 1; i <= grp; i++)
                    if (solved.rd[i] == 0) {
                            #ifdef DEBUG
                            cout << i << endl;
                            #endif
                            ans += rank_g[i];
                    }
            cout << "YES" << endl << ans << endl;
    }
    
    /*main function*/
    int main() {
            memset(visited, 0, sizeof visited);
            memset(rank_g, 127/3, sizeof rank_g);
            ios::sync_with_stdio(false);
            cin >> n;
            cin >> p;
            for (int i = 1; i <= p; i++) {
                    int a, b;
                    cin >> a >> b;
                    basic.edit_rank(a, b);
            }
            cin >> r;
            for (int i = 1; i <= r; i++) {
                    int a, b;
                    cin >> a >> b;
                    basic.push(a, b);
                    reversed.push(b, a);
            }
            /* main process for strong connected graph*/
            for (int i = 1; i <= n; i++)
                    get_dfn(i);
            memset(visited, 0, sizeof visited);
            for (int i = t; i; i--)
                    if (!visited[dfn[i]]) 
                            dfs(dfn[i], ++grp);
            #ifdef DEBUG
            for (int i = 1; i <= n; i++)
                    cout << visited[i] << " ";
            cout << endl;        
            #endif
            memset(hash_tab, 0, sizeof hash_tab);
            for (int i = 1; i <= n; i++)
                    for (int k = basic.head[i]; k; k = basic.edge[k].next) {
                            int to = basic.edge[k].to;
                            if (visited[to] != visited[i] && !hash_tab[visited[i]][visited[to]]) {
                                    solved.push(visited[i], visited[to]);
                                    hash_tab[visited[i]][visited[to]] = 1;
                            }
                    }
            /* main work */
            work();
            return 0;
    }

    注:代码用vscode完成,果然优美2333.

  • 相关阅读:
    shell笔记
    全引用与部分引用
    R语言 EFA(探索性因子分析)
    Markdown 基本使用
    Oracle截取字符串和查找字符串
    ggplot画基本图形类型
    ggplot画图笔记
    用R语言 画条形图(基于ggplot2包)
    Git基本操作
    R语言为数据框添加列名或行名
  • 原文地址:https://www.cnblogs.com/ljt12138/p/6684364.html
Copyright © 2020-2023  润新知