NFLS 图论题单笔记(完结)

news/2024/11/18 21:47:08/文章来源:https://www.cnblogs.com/Kang-shifu/p/18553743

John的农场是一张 N*N 的方格图,贝茜住在左上角(1,1),John住在右下角(N,N)。

现在贝茜要去拜访John,每次都只能往四周与之相邻的方格走,并且每走一步消耗时间 T。

同时贝茜每走三步就要停下来在当前方格吃草,在每个方格吃草的用时是固定的,为 H[i][j]。

John想知道贝茜最少要多久才能到达John的家。

跑一遍djstl。

#include<bits/stdc++.h>
using namespace std;
constexpr int inf = 1e9;
int n, t, h[105][105],d[105][105][5];
int dx[] = {1,-1,0,0,},dy[] = {0,0,1,-1};struct Pr{int a, b;
};
queue<Pr> q,q1;
int main(){cin>>n>>t;for(int i = 1;i <= n;i++)for(int j = 1;j <= n;j++){cin>>h[i][j];}for(int i = 0;i < 105;i++){for(int j = 0;j < 105;j++){d[i][j][0] = d[i][j][1] = d[i][j][2] = d[i][j][3] = d[i][j][4] = inf;}}q.push({1,1}),q1.push({0,0}),d[1][1][0] = 0;while(!q.empty()){for(int i = 0;i < 4;i++){int x = q.front().a + dx[i],y = q.front().b + dy[i];if(x > 0 && x <= n && y > 0 && y <= n){int s = (q1.front().a + 1) % 3,v = q1.front().b+ t + (!s) * h[x][y];if(v < d[x][y][s]){q.push({x,y}),q1.push({s,v}),d[x][y][s] = v;	}}}q.pop(), q1.pop();}cout<<min(d[n][n][0],min(d[n][n][1],d[n][n][2]));
}

给定一个完全图,已知两点之间的距离,以及通过某个点的时间(起点和终点不需要花费时间)。你需要回答一些询问,输出两点之间的最短路径,同时需要输出方案。如果有多个方案,输出字典序最小的方案。

数据范围极小,djstl,同时统计一下路径。



一个n点m边无向图,边权均为1,有k个询问

每次询问给出(s,t,d),要求回答是否存在一条从s到t的路径,长度为d

路径不必是简单路(可以自交)

数据保证不存在自环

由于两个点路径距离为d,就一定存在距离为d+2的路径。所以分层图对每个点跑一边spfa求出每个点到其他点经过奇数路径和偶数路径的距离,然后就可以直接判了。

#include<bits/stdc++.h>
#define N 5005
#define INF 0x3f3f3f3f
using namespace std;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;
}
vector<int> t[N];
int n,m,k,tot,h[N];
bool vis[N],ans[1000005];
int dis[2][N];
struct query{int u,v,w;
}q[1000005];
struct node{int nex,to;
}edge[N<<1];
inline void add(int u,int v){edge[++tot].nex=h[u];edge[tot].to=v;h[u]=tot;
}
inline void spfa(int s){queue<int> Q;for(int i=1;i<=n;i++)dis[0][i]=INF,dis[1][i]=INF,vis[i]=0;Q.push(s);vis[s]=1;dis[0][s]=0;while(!Q.empty()){int x=Q.front();Q.pop();vis[x]=0;for(int i=h[x];i;i=edge[i].nex){int xx=edge[i].to,flg=0;if(dis[0][x]!=INF){if(dis[1][xx]>dis[0][x]+1)dis[1][xx]=dis[0][x]+1,flg=1;}if(dis[1][x]!=INF){if(dis[0][xx]>dis[1][x]+1)dis[0][xx]=dis[1][x]+1,flg=1;}if(flg&&!vis[xx])Q.push(xx),vis[xx]=1;}}
}
int main(){cin>>n>>m>>k;for(int i=1,u,v;i<=m;i++){read(u);read(v);add(u,v);add(v,u);}for(int i=1;i<=k;i++){read(q[i].u),read(q[i].v),read(q[i].w);t[q[i].u].push_back(i);}for(int i=1;i<=n;i++){if(!t[i].size())continue;spfa(i);for(int j=0;j<(int)t[i].size();j++){int o=t[i][j];int num=q[o].w%2;if(q[o].w>=dis[num][q[o].v]&&h[i])ans[o]=1;}}for(int i=1;i<=k;i++)if(ans[i])printf("TAK\n");else printf("NIE\n");return 0;
}

D.公路修建问题

OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多。然而,由于该岛屿刚刚开发不久,所以那 里的交通情况还是很糟糕。所以,OIER Association组织成立了,旨在建立OI island的交通系统。 OI island有n 个旅游景点,不妨将它们从1到n标号。现在,OIER Association需要修公路将这些景点连接起来。一条公路连接两 个景点。公路有,不妨称它们为一级公路和二级公路。一级公路上的车速快,但是修路的花费要大一些。 OIER As sociation打算修n-1条公路将这些景点连接起来(使得任意两个景点之间都会有一条路径)。为了保证公路系统的 效率, OIER Association希望在这n-1条公路之中,至少有k条(0≤k≤n-1)一级公路。OIER Association也不希望为 一条公路花费的钱。所以,他们希望在满足上述条件的情况下,花费最多的一条公路的花费尽可能的少。而你的任 务就是,在给定一些可能修建的公路的情况下,选择n-1条公路,满足上面的条件。

输入格式

第一行有三个数n(1≤n≤10000),k(0≤k≤n-1),m(n-1≤m≤20000),这些数之间用空格分开。N和k如前所述,m表示有m对景点之间可以修公路。

以下的m-1行,每一行有4个正整数a,b,c1,c2(1≤a,b≤n,a≠b,1≤c2≤c1≤30000)

表示在景点a与b之间可以修公路,如果修一级公路,则需要c1的花费,如果修二级公路,则需要c2的花费。



形式化:一张图的边有两种边权,求一棵最小生成树使得至少包含k条第一种边。发现形式化题意看完了也就做完了。

显然出题人不希望我们这样做,如果这道题二级公路可以比一级公路贵这种方法就没法做了,所以可以二分答案,然后每次二分往生成树里放k条一级公路。

#include <bits/stdc++.h>
using namespace std;
const int N=1e4+5,M=2e4+5;
int fa[N];
struct type {int u,v,w,t;int index,choo;
}a[M],b[M];
vector<type> e;
int find(int x){if(x==fa[x]) return x;else return fa[x]=find(fa[x]);
}
void unite(int x,int y){fa[find(x)]=find(y);
}
bool cmp(type a,type b){return a.w<b.w;
}
bool cmp2(type a,type b){return a.t<b.t;
}
bool cmp3(type a,type b){return a.index<b.index;
}
int n,k,m,ta,tb;
int tc1,tc2,m1,ans;
int main()
{cin>>n>>k>>m;for(int i=1;i<=m-1;i++){cin>>ta>>tb>>tc1>>tc2;a[++m1].u=ta,a[m1].v=tb;a[m1].w=tc2,a[m1].t=tc1,a[m1].index=i;}for(int i=1;i<=n;i++) fa[i]=i;sort(a+1,a+m1+1,cmp2);int i;for(i=1;i<=m1&&k;i++){if(find(a[i].u)!=find(a[i].v)){unite(a[i].u,a[i].v);ans=max(ans,a[i].t);k--;a[i].choo=1;e.push_back(a[i]);}}sort(a+i,a+m1+1,cmp);for(;i<=m1;i++){if(find(a[i].u)!=find(a[i].v)){unite(a[i].u,a[i].v);ans=max(ans,a[i].w);a[i].choo=2;e.push_back(a[i]);}}cout<<ans<<endl;//sort(e.begin(),e.end(),cmp3);//for(int i=0;i < (int)e.size();i++)//	cout<<e[i].index<<' '<<e[i].choo<<endl;return 0;
}



吃草

为了庆祝奶牛Bessie的生日,Farmer John给了她一块最好的牧场,让她自由的享用。

牧场上一共有N块草地(1≤N≤1000),编号为1...N,每块草地上牧草的质量都不同。

如果Bessie吃掉的草地上牧草质量为Q,她可以获得Q单位的能量。

每块草地最多和10块草地有相连的道路,在相连的两个草地之间走动需要消耗E单位的能量(1≤E≤1,000,000)。

Bessie可以从任意一块草地开始吃草,并且想要在获得了最多能量的时候停止。

有点遗憾的,Bessie是一头挑食的奶牛,一旦她吃过了一定质量的牧草,她就不会再吃相同或更低质量的牧草!但是她仍然很愿意路过某些草地,而不吃它们。实际上,她发现路过一块高质量的草地而不吃它,等一下返回再去享用,有时会更有利!

请帮忙计算Bessie能够获得的能量的最大值。

发现往返两点之间的最短代价就是最小路径,而最优解的构造方法是从小到大把每块草地的质量排序,然后挨个吃。有的草地吃了它可能会亏,所以就把他踢出去。这样就可以构造一个dp。Fi表示吃第i块草的最大收益。Fi = max(Fj - DISij + VALj)

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn = 2010;
int n, E;
struct edge{int to,next,val;
}e[maxn * 10];
int head[maxn];
int cnt;
void addedge(int u,int v){e[++cnt].to = v;e[cnt].val = E;e[cnt].next = head[u];head[u] = cnt;
}
int dis[maxn][maxn];
bool vis[maxn];
struct node{int dis,pos;bool operator<(const node x) const{return dis > x.dis;}
};
constexpr int inf = 1e9;
void djstl(int S){priority_queue<node> q;for(int i = 0;i < maxn;i++) dis[S][i] = inf,vis[i] = false;q.push((node){0,S});dis[S][S] = 0;while(!q.empty()){node temp = q.top();q.pop();int x = temp.pos;if(vis[x]) continue;vis[x] = true;for(int i = head[x];i;i = e[i].next){int y = e[i].to;if(dis[S][x] + e[i].val < dis[S][y]){dis[S][y] = dis[S][x] + e[i].val;if(!vis[y]){q.push((node){dis[S][y],y});}}}}
}void getdis(){for(int i = 1;i <= n;i++){djstl(i);}
}int dp[maxn];
struct grass{int val,cur;bool operator <(grass x) const{return val < x.val;}
}grass[maxn];int main(){cin>>n>>E;for(int i = 1;i <= n;i++){int q,d;cin>>q>>d;grass[i].val = q;grass[i].cur = i;for(int j = 1;j <= d;j++){int v;cin>>v;addedge(i,v);}}getdis();for(int i=0;i<=n;++i)dis[0][i]=0;sort(grass+1,grass+n+1);for(int i = 1;i <= n;i++) dp[i] = grass[i].val;int ans = 0;for(int i = 1;i <= n;i++){for(int j = 1;j < i;j++){dp[i] = max(dp[i],dp[j] - dis[grass[j].cur][grass[i].cur]+grass[i].val);}ans = max(ans,dp[i]);}cout<<ans<<endl;return 0;
}

最优贸易

image
tarjan缩点,缩完之后从出发点求一遍前缀最大价格,从目的地往前求一遍后缀最小价格。枚举每个节点两个值一减就是答案。

记忆宫殿

image

初始入度为\(0\)的点为源点。

我们令 \(S\) 为如果成立,就能够推出事件的源点集合。

当事件成立时,显然 \(S\) 中的点必有至少一个是真的。所以我们只要把所有包含 \(S\) 的事件都标记为真就行了。

Pro-Professor Szu

某大学校内有一栋主楼,还有 栋住宅楼。这些楼之间由一些单向道路连接,但是任意两栋楼之间可能有多条道路,也可能存在起点和终点为同一栋楼的环路。存在住宅楼无法到达主楼的情况。

现在有一位古怪的教授,他希望每天去主楼上班的路线不同。

一条上班路线中,每栋楼都可以访问任意多次。我们称两条上班路线是不同的,当且仅当两条路线中存在一条路是不同的(两栋楼之间的多条道路被视为是不同的道路)。

现在教授希望知道,从哪些住宅楼前往主楼的上班路线数最多。

到达n+1后,可以选择停下或者继续走



首先发现若一个大小大于 1 的 SCC 或自环(下称为不合法结构)能够到达教学楼,则该不合法结构内部每个点到教学楼的路径数量都是无穷大。

显然可以先缩点,然后拓扑排序。

先将反图上入度为 0 的非教学楼点入队跑一遍拓扑排序。注意此时不合法结构可以入队,因为它们没有到达教学楼的路径。
最后,若出现没有入队的点,说明这个点能够到达一个不合法结构,因此路径数同样为无穷大。此外,若 \(f_i>36500\) 也不符合题意。

自己的代码没调出来,一直不过hack,贴一个题解的,过了就补(已)

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, m, ed, ban[N], deg[N], f[N];
int dn, dfn[N], low[N], cn, col[N], top, stc[N], vis[N];
struct linklist {int cnt, hd[N], nxt[N], to[N];void add(int u, int v) {nxt[++cnt] = hd[u], hd[u] = cnt, to[cnt] = v;}
} e, g;
void tarjan(int id) {dfn[id] = low[id] = ++dn, stc[++top] = id, vis[id] = 1; // 0 -> 1for(int _ = e.hd[id]; _; _ = e.nxt[_]) {int it = e.to[_];if(!dfn[it]) tarjan(it), low[id] = min(low[id], low[it]);else if(vis[it]) low[id] = min(low[id], dfn[it]);}if(low[id] == dfn[id]) {col[id] = ++cn, ban[cn] = stc[top] != id;while(stc[top] != id) col[stc[top]] = cn, vis[stc[top--]] = 0; // id -> cnvis[id] = 0, top--;}
}
int main() {
#ifdef ALEX_WEIfreopen("1.in", "r", stdin);freopen("1.out", "w", stdout);
#endifcin >> n >> m;for(int i = 1; i <= m; i++) {int u, v;scanf("%d%d", &u, &v);e.add(u, v);}for(int i = 1; i <= n + 1; i++) if(!dfn[i]) tarjan(i);for(int i = 1; i <= n + 1; i++)for(int _ = e.hd[i]; _; _ = e.nxt[_]) {int it = e.to[_];if(i == it) ban[col[i]] = 1;else if(col[i] != col[it]) g.add(col[it], col[i]), deg[col[i]]++;}ed = col[n + 1];queue<int> q;for(int i = 1; i <= cn; i++) if(i != ed && !deg[i]) q.push(i);memset(vis, 0, sizeof(vis));while(!q.empty()) {int t = q.front();q.pop(), vis[t] = 1;for(int _ = g.hd[t]; _; _ = g.nxt[_]) {int it = g.to[_];if(!--deg[it] && it != ed) q.push(it);}}if(!ban[ed]) assert(!deg[ed]), q.push(ed), f[ed] = 1;while(!q.empty()) {int t = q.front();q.pop(), vis[t] = 1;for(int _ = g.hd[t]; _; _ = g.nxt[_]) {int it = g.to[_];if(ban[it]) continue;f[it] = min(36501, f[it] + f[t]);if(!--deg[it]) q.push(it);}}vector<int> ans;for(int i = 1; i <= n; i++)if(!vis[col[i]] || f[col[i]] == 36501)ans.push_back(i);if(!ans.empty()) puts("zawsze");else {int mx = 0;for(int i = 1; i <= n; i++) {if(f[col[i]] > mx) mx = f[col[i]], ans.clear();if(f[col[i]] == mx) ans.push_back(i);}cout << mx << "\n";}cout << ans.size() << "\n";for(int it : ans) cout << it << " ";return cerr << "Time: " << clock() << endl, 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Java+SSM+JSP+MYSQL实现的宠物领养收养管理系统功能设计与实现七

基于SSM整合maven开发的一款宠物收养领养管理系统附带源码指导运行视频,该项目前端模板是借鉴别人的,自己写的后台代码,该系统分为前台和后台,前台功能有:登录注册、领养中心、活动中心等。后台管理员功能有:用户管理、宠物管理、活动管理、领养管理、志愿者管理等。该项…

VS上查看某个类中各个成员变量所占用的内存空间

例子 class CTest {char a;int b;double c; };int main() {cout << sizeof(CTest) << endl;return 0; }输入命令 cl ConsoleApplication1.cpp /d1reportSingleClassLayoutCTest其中ConsoleApplication1.cpp 表示这个例子所在的cpp文件名 /d1reportSingleClassLayou…

CUBEMX配置

遥控器配置 cubemx配置在 Connectivity 标签页下将 USART3 打开,将其 Mode 设置为 Asynchronous 异步通讯方式将其波特率设置为 100000,数据帧设置为9位数据位(实测8位有错误),单校验位,1 位停止位接着开启USART3 的 DMA 功能,在 USART3 下找到 DMA Settings 标签呀,在 …

GPR模型的一些高斯原理介绍

一、几个概念区分:高斯的几个概念:高斯分布(Gaussian Distribution):高斯分布是统计学中最常见的概率分布之一,也称为正态分布。它具有钟形曲线的形状,由两个参数决定:均值(mean)和方差(variance)。 高斯分布在自然界和工程应用中经常出现,其形状由均值和方差决定…

20222411 2024-2025-1 《网络与系统攻防技术》实验六实验报告

1.实验内容 1.1 实践内容 (1)前期渗透 ①主机发现(可用Aux中的arp_sweep,search一下就可以use) ②端口扫描:可以直接用nmap,也可以用Aux中的portscan/tcp等。 ③选做:也可以扫系统版本、漏洞等。 (2)Vsftpd源码包后门漏洞(21端口) 漏洞原理:在特定版本的vsftpd服务…

如何控制java虚拟线程的并发度?

jdk 21中的虚拟线程已经推出好一段时间了,确实很轻量,先来一段示例: 假如有一段提交订单的业务代码:1 public void submitOrder(Integer orderId) { 2 sleep(1000); 3 System.out.println("order:" + orderId + " is submitted");…

保险行业客户服务优化:客户运营知识库的实战应用

在保险行业,客户服务优化是提升客户满意度、增强企业竞争力的关键。客户运营知识库作为客户服务的重要支撑,其实战应用对于提升客户服务质量具有重要意义。本文将探讨保险行业客户服务优化的重要性、客户运营知识库的实战应用以及如何利用“HelpLook”工具实现客户服务优化。…

2024-11-18纯碱行情的解浪

图中蓝色线为调整浪ABC线 黄色线为5浪线 纯碱现在走的是ABC-C---->C-5---------5-4 总体来说是大级别的C浪,C浪的5浪,5浪的4浪回调,由于5浪的子2浪是都直的简单调整,5浪的一浪是启动三角形,趋势非常丝滑。这个5浪的子4浪会是大概率 的ABC调整,现在在走B浪还未完成,还…

2024-11-18 PVC分析

5182将是相当长时间的历史大底,这波不会破新低,以后N年也大概率不会破了。多头网格的好品种

ESP32蓝牙学习--蓝牙概念学习

前言 ESP32 是一款同时包含WIFI 蓝牙两者通信方式的芯片,之前学习过WIFI,这次学习一下其蓝牙功能,虽然之前有使用过其他的蓝牙芯片,但大多数都是使用应用层,很少去了解底层协议相关的知识,这一次从概念入手,细致了解一下蓝牙的相关概念,及ESP32相关的工程说明。 蓝牙的…

网络配置及进程-系统性能和计划任务

目录虚拟机联网 shell脚本实例 索引数组和关联数组,字符串处理,高级变量 进程管理 计划任务虚拟机联网 查看IP地址 #centos系列![root@localhost ~]# ifconfig ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.93.200 netmask 255.255.255.…

2024-11-18 大盘分析

牛市已经开始 首先上证季线级别4浪已经完美完成 本次上涨预计最高点位突破11000点再看商品市场 季线级别的3浪已经走完了前4浪,3-5已经启动,3浪的5浪 5of3 与3of3同样的强.3浪的上涨空间是100多一些,5浪可能 会更长。