图论相关问题

这篇具有很好参考价值的文章主要介绍了图论相关问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 拓扑排序+bitset

题目链接:Acwing164 可达性统计

第一次使用bitset,复杂度:N/32,比N小

所以总的时间复杂度为O(N*(N+M)/32)

#include <iostream>
#include <bitset>
#include <queue>
using namespace std;
const int N = 3e4+20;
bitset<N> f[N];
struct NODE{
    int to, next;
}edge[N];
int head[N], cnt, inv[N], n, m;
void add(int u, int v) {
    ++cnt;
    edge[cnt].to = v, edge[cnt].next = head[u], head[u] = cnt;
}

void topo() {
    queue<int> q;
    for(int i=1; i<=n; i++) {
        if(!inv[i]) q.push(i);
    }
    while(!q.empty()) {
        int x = q.front();
        q.pop();
        f[x][x] = 1; //自己可到达
        for(int i = head[x]; i; i = edge[i].next) {
            int v = edge[i].to;
            f[v] |= f[x];
            inv[v]--;
            if(!inv[v]) q.push(v);
        }
    }
    
    for(int i=1; i<=n; i++) printf("%d\n", f[i].count()); //二进制中1的个数
}

int main() {
    int u, v; scanf("%d%d", &n, &m);
    while(m--){
        scanf("%d%d", &u, &v);
        add(v, u); //反向建图
        inv[u]++;
    }
    topo();
    return 0;
}
2. 01分数规划, spfa判断正环

题目链接:Acwing 观光奶牛

图论相关问题,算法

#include <bits/stdc++.h>
using namespace std;
const int N = 1050, M = 5005;
int head[N], cnt, n, ct[N], st[N];
double dis[N], f[N];
struct NODE{
    int to, next, w;
}edge[M];

void add(int u, int v, int w){
    ++cnt;
    edge[cnt].to = v, edge[cnt].next = head[u], head[u] = cnt;
    edge[cnt].w = w;
}

bool spfa(double mid) {
    queue<int> q;
    for(int i=1; i<=n; i++) q.push(i), st[i] = true, dis[i] = ct[i] = 0;
    
    while(!q.empty()) {
        int x = q.front();
        q.pop();
        st[x] = false;
        for(int i = head[x]; i; i = edge[i].next) {
            int v = edge[i].to;
            if( dis[v] < dis[x] + f[x] - mid * edge[i].w) { //判断正环
                dis[v] = dis[x] + f[x] - mid * edge[i].w;
                ct[v] = ct[x]+1;
                if(ct[v] >= n) return true;
                if(!st[v]) {
                    q.push(v), st[v] = true;
                }
            }
        }
    }
    
    return false;
}
int main() {
    int p; scanf("%d%d", &n, &p);
    for(int i=1; i<=n; i++) cin >> f[i];
    int a, b, w;
    while(p--) {
        scanf("%d%d%d", &a, &b, &w);
        add(a, b, w);
    }
    double l = 0, r = 1010, eps = 1e-4;
    while(r-l > eps) {
        double mid = (l+r)/2;
        if(spfa(mid)) l = mid;
        else r =mid;
    }
    printf("%.2lf", l);
    return 0;
}
3. dp, 统计s点到t点的最短路/次短路有多少条

题目链接:cf div3. G. Counting Shortcuts

需要注意dp的转移顺序文章来源地址https://www.toymoban.com/news/detail-661433.html

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5+10, M = 4e5+10, mod = 1e9+7;
int st, ed;
bool walked[N];
int cnt, head[N], depth[N];
vector<int> vec[N];
ll dp[N][2]; //dp[i][0/1]代表从s到i点为最/次短路有多少条路径
struct EDGE{
	int to, next;
}edge[M];
void add(int u, int v){
	++cnt;
	edge[cnt].to = v, edge[cnt].next = head[u], head[u] = cnt;
}
void bfs(){
	queue<int> q;
	q.push(st);
	walked[st] = 1;
	depth[st] = 0;
	while(!q.empty()){
		int x = q.front();
		q.pop();
		for(int i = head[x]; i; i = edge[i].next){
			int v = edge[i].to;
			if(walked[v]) continue;
            q.push(v);
			walked[v] = 1;
			depth[v] = depth[x]+1;
		}
	}
}

int main() {
	int T; scanf("%d", &T);
	while(T--){
		int n, m, u, v; scanf("%d%d", &n, &m);
		for(int i = 1; i<=n; i++) head[i] = walked[i] = dp[i][0] = dp[i][1] = 0;
		for(int i = 1; i<=cnt; i++) edge[cnt].to = edge[cnt].next = 0;
		cnt = 0;
		scanf("%d%d", &st, &ed);
		while(m--){
			scanf("%d%d", &u, &v);
			add(u, v), add(v, u);
		}
		bfs(); //处理出深度 
        for(int i = 0; i<=depth[ed]; i++) vec[i].clear();
		for(int i = 1; i<=n; i++) {
            vec[depth[i]].emplace_back(i);
        }
        dp[st][0]= 1;
        for(int i = 0; i <= depth[ed]; i++) { //枚举深度
            for(int j = 0; j<vec[i].size(); j++){ //先转移同一层的
                int uu = vec[i][j]; //深度为i的点uu
                for(int k = head[uu]; k; k = edge[k].next) {
                    int vv = edge[k].to; //与uu相邻的点vv
                    if(depth[vv]==i) dp[vv][1] = (dp[vv][1] + dp[uu][0])%mod;
                }
            }
            for(int j = 0; j<vec[i].size(); j++){ //再转移下一层的
                int uu = vec[i][j]; //深度为i的点uu
                for(int k = head[uu]; k; k = edge[k].next) {
                    int vv = edge[k].to; //与uu相邻的点vv
                    if(depth[vv]==i+1) dp[vv][0] = (dp[vv][0] + dp[uu][0])%mod, dp[vv][1] = (dp[vv][1] + dp[uu][1])%mod;
                }
            }
        }
        ll ans = (dp[ed][1] + dp[ed][0])%mod;
        printf("%lld\n", ans);
	}
	return 0;
}

//因为该层的dp[0], dp[1]转移给下一层的dp[0], dp[1]
//而该层的dp[0]由上一层转移而来(没有问题),而该层的dp[1]却还可以由同一层的dp[0]转移而来
//因此我们应该先把该层的dp[1]转移完,再把本层的转移给下一层

到了这里,关于图论相关问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图论与算法(7)最短路径问题

    最短路径问题是指在一个加权图中寻找两个顶点之间的最短路径,其中路径的长度由边的权重确定。 常见的最短路径算法包括: Dijkstra算法 :适用于解决单源最短路径问题,即从一个固定的起点到图中所有其他顶点的最短路径。该算法通过不断选择当前路径上权重最小的顶

    2024年02月06日
    浏览(41)
  • 算法随笔:图论问题之割点割边

    割点的定义:如果一个点被删除之后会导致整个图不再是一个连通图,那么这个顶点就是这个图的割点。举例:  上图中的点2就是一个割点,如果它被删除,则整个图被分为两个连通分量,不再是一个连通图。 最直观容易想到的一种简单朴素的方法: 依次删除每一个顶点,

    2024年02月13日
    浏览(34)
  • 【计算机算法】【图论】【最优匹配与点云对准问题】最(极)大团算法

    团与最大团的定义 图顶点集的子集满足任意两个顶点相邻,称该子集是该图的一个团。图的所有团中顶点最多的,即最大的一个或多个,称为图的最大团或极大团。 图的最大团的实际应用问题 CVPR2023最佳论文之一用最大团算法实现鲁棒的点云对准,有效解决外点问题。顾名

    2024年03月15日
    浏览(37)
  • 【图论】中国邮递员问题、平面图上最大割问题的多项式时间算法

    中国邮递员问题(Chinese Postman Problem, CPP)是图论中的一个著名问题,它是在1960年由我国学者管梅谷首先提出并研究的。简单来说,就是问:一个邮递员从邮局出发,把一个城市的所有街道都至少走一遍,最后回到邮局,问怎样使他走的总路程最小?这个问题有许多现实的应

    2024年02月12日
    浏览(38)
  • 数学建模十大算法04—图论算法(最短路径、最小生成树、最大流问题、二分图)

    一、最短路径问题 从图中的某个顶点出发,到达另一个顶点的 所经过的边的权重之和最小 的一条路径。 1.1 两个指定顶点之间的最短路径 问题如下:给出了一个连接若干个城镇的铁路网络,在这个网络的两个指定城镇间,求一条最短铁路线。 1.1.1 Dijkstra算法 迪杰斯特拉(D

    2024年02月02日
    浏览(71)
  • 图论相关基本概念

    从逻辑结构上讲,图是一种典型的 非线性结构 。 图(Graph) 是由 顶点的有穷非空集合和顶点之间边的集合 组成的,通常表示为 G(V , E) ,其中, G表示—个图,V是图G中顶点的集合,E是图G中边的集合。其中: 顶点集合V={x|x属于某个数据对象集}是有穷非空集合 E={(x,y)|

    2024年02月01日
    浏览(37)
  • PAT甲级图论相关题目

    PAT甲级图论相关题目: 分数 25 As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some o

    2024年01月21日
    浏览(52)
  • 【leetcode:1944. 队列中可以看到的人数】单调栈算法及其相关问题

    1944. 队列中可以看到的人数 有  n  个人排成一个队列, 从左到右  编号为  0  到  n - 1  。给你以一个整数数组  heights  ,每个整数  互不相同 , heights[i]  表示第  i  个人的高度。 一个人能  看到  他右边另一个人的条件是这两人之间的所有人都比他们两人  矮  。更

    2024年01月25日
    浏览(34)
  • 图论相关题-pta-个人整理-含有解析

    例题1 7-1 邻接矩阵表示法创建无向图 分数 20 作者 王东 单位 贵州师范学院 采用邻接矩阵表示法创建无向图G ,依次输出各顶点的度。 输入格式: 输入第一行中给出2个整数i(0i≤10),j(j≥0),分别为图G的顶点数和边数。 输入第二行为顶点的信息,每个顶点只能用一个字符表示

    2024年02月04日
    浏览(50)
  • 算法-回溯相关问题-生成所有n位长的二进制字符串 Java版

    生成所有n位长的二进制字符串。假设A[0…n-1]是一个大小为n的数组。

    2024年02月16日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包