图论之路径条数专题

一直忙着金工实习+蓝桥杯,好久没有看图论了,今天就小试几题享受下被虐的快感。

1.最短路+拓扑

首先来几个结论:

1.最短路图没有环(可以用反证法证明)

2.dis[u]+edge[u,v]=dis[v],那么u,v端点的边一定在最短路图上。

因此,我们就可以先枚举起始点跑SPFA,然后把最短路找出来,假如一个边的端点为u,v,那么经过它的为cnt1[u]*cnt2[v],cnt1为正着最短路图上过u的边,cnt2为反着(注意到v结束也是一种,所以结尾后+1)。

因此,我们求两边拓扑排序即可,下面是AC代码(这里正反图用奇偶存储来区别):

#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;

const int N=1502;
const int M=100010;
bool vis[N];
int dis[N],in1[N],in2[N],cnt1[N],cnt2[N];
int n,m,u,v,w,head[N],is[M],cnt=1;
int ans[M];
struct node{
	int dian,next,zhi;
}edge[M];
void add(int u,int v,int w){//i&1为反图 
	edge[++cnt].dian=v;
	edge[cnt].zhi=w;
	edge[cnt].next=head[u];
	head[u]=cnt;
	edge[++cnt].dian=u;
	edge[cnt].zhi=w;
	edge[cnt].next=head[v];
	head[v]=cnt; 
}
void spfa(int s){
	memset(vis,0,sizeof(vis));
	memset(dis,0x7f7f7f7f,sizeof(dis));
	queue<int> q;
	vis[s]=1;
	q.push(s);
	dis[s]=0;
	while(!q.empty()){
		int ck=q.front();
		q.pop();
		vis[ck]=0;
		for(int i=head[ck];i!=-1;i=edge[i].next){
			if(i&1) continue;
			if(dis[edge[i].dian]>dis[ck]+edge[i].zhi){
				dis[edge[i].dian]=dis[ck]+edge[i].zhi;
				if(!vis[edge[i].dian]){
					vis[edge[i].dian]=1;
					q.push(edge[i].dian);
				}
			}
		}
	}
}
void new1(){
	memset(is,0,sizeof(is));
	memset(in1,0,sizeof(in1));
	memset(in2,0,sizeof(in2));
	for(int u=1;u<=n;u++){
		for(int i=head[u];i!=-1;i=edge[i].next){
			if(i&1) continue;
			if(dis[u]+edge[i].zhi==dis[edge[i].dian]){
				is[i]=1;
				is[i^1]=1;
				in1[edge[i].dian]++;
				in2[u]++;
			}
		}
	}
}
void topo(int s){
	memset(cnt1,0,sizeof(cnt1));
	memset(cnt2,0,sizeof(cnt2));
	queue<int> q;
	q.push(s);
	cnt1[s]=1;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=head[u];i!=-1;i=edge[i].next){
			if(!is[i]||(i&1)) continue;
			int v=edge[i].dian;
			in1[v]--;
			cnt1[v]=(cnt1[v]+cnt1[u])%mod;
			if(!in1[v]) q.push(v);
		}
	}
	for(int i=1;i<=n;i++){
		if(!in2[i]){
			cnt2[i]=1;
			q.push(i);
		}
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=head[u];i!=-1;i=edge[i].next){
			if(!is[i]||!(i&1)) continue;
			int v=edge[i].dian;
			in2[v]--;
			cnt2[v]=(cnt2[v]+cnt2[u])%mod;
			if(!in2[v]){
				q.push(v);
				cnt2[v]++;//自己 
			}
		}
	}
}
void cal(){
	for(int u=1;u<=n;u++){
		for(int i=head[u];i!=-1;i=edge[i].next){
			if((i&1)||!is[i]) continue;
			int v=edge[i].dian;
			ans[i>>1]=(ans[i>>1]+cnt1[u]*cnt2[v]%mod)%mod;
		}
	}
}
void solve(){
	for(int i=1;i<=n;i++){
		spfa(i);
		new1();
		topo(i);
		cal();
	}
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}
int main(){
	cin>>n>>m;
	memset(head,-1,sizeof(head));
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
	}
	solve();
	return 0;
}

2.最短路+DP

首先跑个最短路,然后我们令f[i][j]表示走到i不超过d+j的条数。

易得状态转移方程:f[x][k]=\sum(f[y][dis[x]+k-dis[y]-len2[x][y])%p;

至于顺序我们直接记忆化搜素即可。

这里有个比较麻烦的细节:

如何判断0环?

1.不是一有0环就-1,当你的0环不在最短路+k涉及的路径上它起不了作用,那么这如何判?

注意到此时dis[x]+k-dis[y]-len2[x][y]为负值,我们判一下这种情况即可。

2.当一个二维位置即同一个点,同一个小于距离出现时,说明0环,判-1.

因此我们还要用v[n][55]来记录有没有访问过(注意dfs完后归0操作)

3.注意到0环涉及起点1的情况,这也是为什么起点设在n+1源点而不是1的原因。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100000;
int t,n,m,k,p,a,b,c,flag;
vector<int> edge[N+1],len[N+1];
vector<int> edge1[N+1],len2[N+1];
int dis[N+1],vis[N+1];
int f[N+1][55];
bool v[N+1][55];
struct ty{
    int x,dis;
    bool operator< (const ty &a) const{
        return dis>a.dis;
    }
};
priority_queue<ty> q;
void dij(int s){
    memset(dis,0x7f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[s]=0;
    q.push({s,0});
    while(!q.empty()){
        ty tmp=q.top();
        q.pop();
        if(vis[tmp.x]) continue;
        vis[tmp.x]=1;
        for(int i=0;i<edge[tmp.x].size();i++){
            int y=edge[tmp.x][i];
            if(dis[y]>dis[tmp.x]+len[tmp.x][i]){
                dis[y]=dis[tmp.x]+len[tmp.x][i];
                q.push({y,dis[y]});
            }
        }
    }
}
int dfs(int x,int k){
    if(f[x][k]!=-1) return f[x][k];
    f[x][k]=0;
    v[x][k]=1;
    for(int i=0;i<edge1[x].size();i++){
        int y=edge1[x][i];
        int t=dis[x]+k-dis[y]-len2[x][i];
        if(t<0) continue;
        if(v[y][t]) flag=1;
        if(flag) return 0;    
        f[x][k]=(f[x][k]+dfs(y,t))%p;
    }
    v[x][k]=0;
    return f[x][k];
}
int main(){
    cin>>t;
    while(t--){
        scanf("%d%d%d%d",&n,&m,&k,&p);
        for(int i=1;i<=n+1;i++){
            edge[i].clear();
            len[i].clear();
            edge1[i].clear();
            len2[i].clear();
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&a,&b,&c);
            edge[a].push_back(b);
            len[a].push_back(c);
            edge1[b].push_back(a);
            len2[b].push_back(c);
        }
        edge[n+1].push_back(1);
        len[n+1].push_back(0);
        edge1[1].push_back(n+1);
        len2[1].push_back(0);
        dij(n+1);
        memset(f,-1,sizeof(f));
        memset(v,0,sizeof(v));
        f[n+1][0]=1;
        int ans=0;
        flag=0;
        for(int i=0;i<=k;i++){
            ans=(ans+dfs(n,i))%p;
        }
        if(flag) printf("-1\n");
        else printf("%d\n",ans);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/497417.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【已修复】iPhone13 Pro 长焦相机水印(黑斑)修复 洗水印

iPhone13 Pro 长焦相机水印&#xff08;黑斑&#xff09;修复 洗水印 问题描述 iPhone13 Pro 后摄3倍相机有黑色斑点&#xff08;水印&#xff09;&#xff0c;如图所示&#xff0c; 后摄相机布局如图所示&#xff0c; 修复过程 拆机过程有风险&#xff0c;没有把握最好不要…

Git--08--Git分支合并操作

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Git分支合并操作案例流程客户端&#xff1a;GitExtensions操作步骤&#xff1a;A操作步骤&#xff1a;B操作步骤&#xff1a;C操作步骤&#xff1a;D操作步骤&#…

NanoMQ的安装与部署

本文使用docker进行安装&#xff0c;因此安装之前需要已经安装了docker 拉取镜像 docker pull emqx/nanomq:latest 相关配置及密码认证 创建目录/usr/local/nanomq/conf以及配置文件nanomq.conf、pwd.conf # # # # MQTT Broker # # mqtt {property_size 32max_packet_siz…

每日一题--最长连续序列

洛阳春-岑参 人到洛阳花似锦&#xff0c;偏我来时不逢春。 谁道三冬无春色&#xff0c;冰山高处万里银 目录 题目描述 思路分析 方法及其时间复杂度 法一 暴力枚举&#xff1a; 法二 哈希表遍历&#xff1a; 法三 并查集&#xff1a; 个人总结 题目描述 128. 最长连续序…

【网安小白成长之路】3.MySQL环境配置以及常用命令(增删改查)

&#x1f42e;博主syst1m 带你 acquire knowledge&#xff01; ✨博客首页——syst1m的博客&#x1f498; &#x1f51e; 《网安小白成长之路(我要变成大佬&#x1f60e;&#xff01;&#xff01;)》真实小白学习历程&#xff0c;手把手带你一起从入门到入狱&#x1f6ad; &…

Day53:WEB攻防-XSS跨站SVGPDFFlashMXSSUXSS配合上传文件添加脚本

目录 MXSS UXSS&#xff1a;Universal Cross-Site Scripting HTML&SVG&PDF&SWF-XSS&上传&反编译(有几率碰到) SVG-XSS PDF-XSS Python生成XSS Flash-XSS 知识点&#xff1a; 1、XSS跨站-MXSS&UXSS 2、XSS跨站-SVG制作&配合上传 3、XSS跨站-…

项目模块—实现抑郁测评(小程序)

script <script setup> import { ref } from "vue";//控制轮播图页码 let current ref(0);//答题逻辑 const add (value) > {if (current.value < 9) {current.value current.value 1;} else {uni.switchTab({url: "/pages/my/my",});} }…

「DevExpress中文教程」如何将DevExtreme JS HTML编辑器集成到WinForms应用

在本文中我们将演示一个混合实现&#xff1a;如何将web UI工具集成到WinForms桌面应用程序中。具体来说&#xff0c;我们将把DevExtreme JavaScript WYSIWYG HTML编辑器(作为DevExtreme UI组件套件的一部分发布的组件)集成到Windows Forms应用程序中。 获取DevExtreme v23.2正式…

Vue3进阶教程-第2学堂小商城实战课程前言

该教程为进阶教程&#xff0c;如果你还不了解Vue3的基础知识&#xff0c;可以先前往Vue3基础教程&#xff0c;从入门到实战。 学习时遇到的任何疑问都欢迎在相应课文页面下方的问答区进行提问哦 我能学到什么&#xff1f; 编程写法千千万&#xff0c;实现需求是第一。 教程中…

阿里云服务器租用价格表-2024最新(附报价单)

2024年阿里云服务器优惠价格表&#xff0c;一张表整理阿里云服务器最新报价&#xff0c;阿里云服务器网aliyunfuwuqi.com整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单&#xff0c;大家也可以直接移步到阿里云CLUB中心查看 aliyun.club 当前最新…

数据结构——链表(练习题)

大家好&#xff0c;我是小锋我们继续来学习链表。 我们在上一节已经把链表中的单链表讲解完了&#xff0c;大家感觉怎么样我们今天来带大家做一些练习帮助大家巩固所学内容。 1. 删除链表中等于给定值 val 的所有结点 . - 力扣&#xff08;LeetCode&#xff09; 我们大家来分…

登录拦截器

目录 &#x1f388;1.登陆拦截器的使用 &#x1f38a;2.ThreadLocal的简单使用 &#x1f383;3.登录拦截器拦截和放行配置 1.登陆拦截器的使用 创建一个拦截器类&#xff0c;必须让其实现HandlerInterceptor接口 1.获取前端的token 2.判断token是否为空 3.若为空&#xff…

蓝桥杯基础练习详细解析(四)——Fibonacci费伯纳西数列(题目分析、代码实现、Python)

试题 基础练习 Fibonacci数列 提交此题 评测记录 资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 Fibonacci数列的递推公式为&#xff1a;FnFn-1Fn-2&#xff0c;其…

CI/CD实战-jenkins结合ansible

配置主机环境 在jenkins上断开并删除docker1节点 重新给master添加构建任务 将server3&#xff0c;server4作为测试主机&#xff0c;停掉其上后面的docker 在server2&#xff08;jenkins&#xff09;主机上安装ansible 设置jenkins用户到目标主机的免密 给测试主机创建用户并…

swagger/knife4j 接口文档增加图标 springboot

1.在资源目录下增加图标文件 2.配置/favicon.ico 资源 Configuration public class WebConfig implements WebMvcConfigurer {Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/favicon.ico").addResour…

小程序利用WebService跟asp.net交互过程发现的问题并处理

最近在研究一个项目&#xff0c;用到asp.net跟小程序交互&#xff0c;简单的说就是小程序端利用wx.request发起请求。获取asp.net 响应回来的数据。但经常会报错。点击下图的测试按钮 出现如下错误&#xff1a; 百思不得其解&#xff0c;试了若干方法&#xff0c;都不行。 因为…

axios发送get请求但参数中有数组导致请求路径多出了“[]“的处理办法

一、情况 使用axios发送get请求携带了数组参数时&#xff0c;请求路径中就会多出[]字符&#xff0c;而在后端也会报错 二、解决办法 1、安装qs 当前项目的命令行中安装 npm install qs2、引入qs库(使用qs库来将参数对象转换为字符串) // 全局 import qs from qs Vue.proto…

Vite 为什么比 Webpack 快?

目录 1. Webpack 的构建原理 2. Script 的模块化&#xff08;主流浏览器对 ES Modules 的支持&#xff09; 3. Webpack vs Vite 开发模式的差异 对 ES Modules 的支持 底层语言的差异 热更新的处理 1. Webpack 的构建原理 前端之所以需要类似于 Webpack 这样的构建工具&…

智慧工地安全生产与风险预警大平台的构建,需要哪些技术?

随着科技的不断发展&#xff0c;智慧工地已成为现代建筑行业的重要发展趋势。智慧工地方案是一种基于先进信息技术的工程管理模式&#xff0c;旨在提高施工效率、降低施工成本、保障施工安全、提升施工质量。一般来说&#xff0c;智慧工地方案的构建&#xff0c;需要通过集成物…

kubernetes(K8S)学习(一):K8S集群搭建(1 master 2 worker)

K8S集群搭建&#xff08;1 master 2 worker&#xff09; 一、环境资源准备1.1、版本统一1.2、k8s环境系统要求1.3、准备三台Centos7虚拟机 二、集群搭建2.1、更新yum&#xff0c;并安装依赖包2.2、安装Docker2.3、设置hostname&#xff0c;修改hosts文件2.4、设置k8s的系统要求…
最新文章