-刷题小结

P1993 小 K 的农场 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路:

第一种:a-b>=c也就是b-a<=-c

第二种:b-a<=c

第三种:a=b

上面三种也就是差分约束,换种意思也就是:

一:b到a的距离为-c
二:   b到a的距离为c

三:b到a的距离为0

使用bellmanford算法,若出现了负环我们就可以知道无法满足上面的这三种要求
代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<algorithm>
#include<bits/stdc++.h>
#include<cmath>
#include<cstring>
#include<iostream>
#include<map>
#include<queue>
#include<stdio.h>
#include<unordered_map>
#include<unordered_set>
#include<vector>
using namespace std;
typedef long long ll;
#define TT 	ll t;cin >> t;while (t--);
#define IOS ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
const int N = 2e6 + 10;
struct node {
	int ids, dis;
};
int n, m, a, b, c, w[N], f[N], cnt[N], t;
vector<node>arr[N];
int spfa() {
	queue<int>q;
	for (int i = 1; i <= n; i++)w[i] = 1e9, f[i] = 1, q.push(i);
	w[1] = 0;
	while (!q.empty()) {
		int u = q.front(); q.pop();
		f[u] = 0;
		for (int i = 0; i < arr[u].size(); i++) {
			int v = arr[u][i].ids;
			int dis = w[u] + arr[u][i].dis;
			if (dis >= w[v])continue;
			w[v] = dis;
			if (f[v])continue;
			f[v] = 1;
			q.push(v);
			cnt[v]++;
			if (cnt[v] >= n)return 0;
		}
	}
	return 1;
}
void solve() {
	cin >> n >> m;
	for (int i = 1; i <= m; i++) {
		cin >> t >> a >> b;
		if (t == 3) {
			arr[a].push_back({ b,0 });
			arr[b].push_back({ a,0 });
		}
		else {
			cin >> c;
			if (t == 1)arr[b].push_back({ a,-c });
			else {
				arr[a].push_back({ b,c });
			}
		}
	}
	if (spfa())cout << "Yes\n";
	else cout << "No\n";
	return;
}
int main(){	
	IOS;
	solve();
	return 0;
}

P1119 灾后重建 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路:

用一个二维数组来存图即可,从第0号村庄开始,每重建一个村庄都要全部更新路径的长度(因为每通一个村庄,最短路径会发生改变),再判断两个村庄u,v此时的时间是否在允许的范围内,若在则输出最短路径,不在则输出-1

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<algorithm>
#include<bits/stdc++.h>
#include<cmath>
#include<cstring>
#include<iostream>
#include<map>
#include<queue>
#include<stdio.h>
#include<unordered_map>
#include<unordered_set>
#include<vector>
using namespace std;
typedef long long ll;
#define TT 	ll t;cin >> t;while (t--);
#define IOS ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
const int N = 2e6 + 10;
ll t[N], a[210][210], u, v, w, n, m, q;
void floyed(int k) {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			a[i][j] = min(a[i][j], a[i][k] + a[k][j]);
		}
	}
}
void solve() {
	cin >> n >> m;
	memset(a, 0x3f, sizeof(a));
	for (int i = 0; i < n; i++)cin >> t[i];
	for (int i = 0; i < m; i++) {
		cin >> u >> v >> w;
		a[u][v] = w;
		a[v][u] = w;
	}
	for (int i = 0; i < n; i++)a[i][i] = 0;
	cin >> q;
	int i = 0;
	t[n] = 1e9;
	while (q--) {
		cin >> u >> v >> w;
		while (t[i] <= w)floyed(i++);
		if (t[u] > w || t[v] > w || a[u][v] > 1e9) {
			cout << "-1\n";
		}
		else {
			cout << a[u][v] << "\n";
		}
	}
	return;
}
int main(){	
	IOS;
	solve();
	return 0;
}

Educational Codeforces Round 170 (Rated for Div. 2)

Problem - C - Codeforces

思路:借鉴了jiangly大神的方法,感觉非常简便,题意是在一个数组中根据规则找到最大值(规则:第一次任意选一个数,从第二次开始每次选的数只能等于前一个数或比前一个数大1,这样的数最多不能超过k个)

代码:

void solve() {
    ll n, k;
    cin >> n >> k;
    vector<ll>a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    sort(a.begin(), a.end());//升序排序,从最小的开始
    int ans = 0;
    for (int i = 0, j = 0; i < n; i++) {
    //1.确保不越界  2.保证符合规则  3.因为相邻的数最大差值为1,所以需要判断当前数和第一次的选定数之间的差值是否在k以内
        while (j + 1 < n && a[j + 1] <= a[j] + 1 && a[j + 1] < a[i] + k) {
            j++;
        }
        ans = max(j - i + 1, ans);//更新最大值,+1的原因是本身也算一次
    }
    cout << ans << "\n";
    return;
}

https://codeforces.com/contest/2025/problem/B
思路:用错误的公式进行遍历之后可以发现规律,即每一次的输出都是pow(2,k[i])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值