• 一天一道算法题——图


    前些天做了好几道关于图的题,现在来个整理。

    图的概念就不介绍了。

    记u为起点,v为终点

    最简单的存储方式:

    vector<int> g[maxn];

    在上面的vector里,如果正向建图,那么再输入的时候g[u].push_back(v);

    如果反向建图,那么就是g[v].push_back(u);

    以下是一个关于反向建图并dfs遍历的题目。

    P3916 图的遍历

    AC代码:

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<stdio.h>
     4 #include<vector>
     5 #define maxn 100010
     6 using namespace std;
     7 
     8 int n, m, vis[maxn];
     9 vector<int> g[maxn];
    10 
    11 void dfs(int x,int d) {
    12     if (vis[x])return;
    13     vis[x] = d;
    14     for (int i = 0; i < g[x].size(); i++) {
    15         dfs(g[x][i], d);
    16     }
    17 }
    18 
    19 int main() {
    20     cin >> n >> m;
    21     int u, v;
    22     for (int i = 1; i <= m; i++) {
    23         scanf("%d%d", &u, &v);
    24         g[v].push_back(u);//反向建图
    25     }
    26     for (int i = n; i >= 1; i--)dfs(i, i);
    27     for (int i = 1; i <= n; i++)printf("%d ", vis[i]);
    28     return 0;
    29 }
    View Code

    正向的思路很复杂,但用逆向思维思考的话,代码就会非常简单。

    然后第二个示例,是当要求图的存储进行排序的情况。

     1 struct edge {
     2     int u, v;//u起点,v终点
     3 }tmp;
     4 vector<int> e[100010];
     5 vector<edge> s;
     6 while (m--) {
     7     scanf("%d%d", &tmp.u, &tmp.v);
     8     s.push_back(tmp);
     9 }
    10 sort(s.begin(), s.end(), cmp);
    11 for (int i = 0; i < s.size(); i++) {
    12     e[s[i].u].push_back(i);
    13 }

    情况稍微变的有点复杂,代码里的e同上个示例中的g,作用不变。但在排序(代码中假定是对每个相同的起点,按终点大小排列)的时候,需要建一个临时的vector s当存储。

    相应的cmp

    inline bool cmp(edge a, edge b) {
        if (a.v == b.v)return a.u < b.u;
        return a.v < b.v;
    }

    题目:P5318【深基18.例3】查找文献

    接下来是拓扑排序

    拓扑排序是对有向无环图的顶点的一种排序,它使得如果存在一条从顶点A到顶点B的路径,那么在排序中B出现在A的后面。

    由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止。

    (1) 选择一个入度为0的顶点并输出之;

    (2) 从网中删除此顶点及所有出边。

    循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列。

    题目:P1113杂务

    代码:

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<stdio.h>
     4 #include<queue>
     5 using namespace std;
     6 const int N = 10010;
     7 queue<int> q;
     8 bool e[N][N];
     9 int n,ans,ti[N], mx[N], ru[N];
    10 
    11 void topo() {
    12     for (int i = 1; i <= n; i++) {
    13         if (ru[i] == 0) {//将入度为0的顶点放进q里
    14             q.push(i);
    15             mx[i] = ti[i];
    16         }
    17     }
    18     while (!q.empty()) {
    19         int d = q.front();//前序工作时间已经加上的顶点
    20         q.pop();
    21         for (int i = 1; i <= n; i++) {
    22             if (e[d][i]) {
    23                 ru[i]--;
    24                 if (ru[i] == 0)q.push(i);
    25                 mx[i] = max(mx[i], mx[d] + ti[i]);
    26             }
    27         }
    28     }
    29     for (int i = 1; i <= n; i++)
    30         ans = max(ans, mx[i]);
    31 }
    32 
    33 int main() {
    34     cin >> n;
    35     for (int i = 1; i <= n; i++) {
    36         int a, b, c;
    37         scanf("%d%d%d", &a, &b, &c);
    38         ti[a] = b;
    39         while (c != 0) {
    40             ru[a]++;//入度
    41             e[c][a] = true;//图的创立
    42             scanf("%d", &c);
    43         }
    44     }
    45     topo();//拓扑排序
    46     printf("%d", ans);
    47     return 0;
    48 }
  • 相关阅读:
    fetch
    创建Vue实例传入的option
    Text and Binary modes
    daemon_int
    http 协议 c++代码 获取网页
    asp.net mvc 5 初体验
    win32 音视频相关 api
    setuid和seteuid
    用0x077CB531计算末尾0的个数
    webservice gsoap 小记
  • 原文地址:https://www.cnblogs.com/zyyz1126/p/12695722.html
Copyright © 2020-2023  润新知