SDUTACM20级集训队2022春季选拔赛2 补题(Codeforces Gym 102501 A F K)
A-Environment-Friendly Travel
题意:
给定一些交通工具,\(n\)个地点的坐标位置,\(T\)个交通工具的每公里碳排放量,起点和终点的位置,能走的最大距离\(B\),问从起点到终点跑不超过距离\(B\)的情况下的最小碳排放量
思路:
定义\(f(i,dis)\)为到达位置\(i\),行驶了\(dis\)距离的最小碳排放量
比模板的最短路多了一维,二维\(dijkstra\)
把(i,dis)看成一维里的点或者状态,\(f(i,dis)\)就看成一维状态的最小代价
最后,在距离\(<=\)B情况下,取\(min\)即可
注意开\(long long\)
Vie Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
const int N = 2222;
const int M = N * N;
const int inf = 1e18;
typedef pair<int, int> PII;
struct node {
int x, y;
} pos[N];
struct Point {
int p;
int co2;
int distance;
bool operator<(const Point &t) const {
if (co2 != t.co2) return co2 > t.co2;
return distance > t.distance;
}
};
int CO[N][N];
int vis[N][N];
int h[M], e[M], ne[M], co[M], w[M], idx;
vector<PII> g[N];
node st, ed;
int B, C[N];
int T, n;
void add_edge(int a, int b, int dis, int val) {
e[idx] = b, ne[idx] = h[a], co[idx] = val, w[idx] = dis, h[a] = idx++;
}
int cal(node a, node b) {
return ceil(
sqrt(1.0 * (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)));
}
void dijkstra() {
priority_queue<Point> q;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
CO[i][j] = inf;
}
}
CO[0][0] = 0;
q.push({0, 0, 0});
int cnt = 0;
while (!q.empty()) {
auto t = q.top();
q.pop();
int now = t.p;
int nco2 = t.co2;
int dist = t.distance;
if (vis[now][dist]) continue;
vis[now][dist] = 1;
for (int i = h[now]; ~i; i = ne[i]) {
int j = e[i];
int co2 = co[i];
if (w[i] + dist > B) continue;
//去掉无用的状态,防止超时
if (CO[j][w[i] + dist] > CO[now][dist] + co[i]) {
CO[j][w[i] + dist] = CO[now][dist] + co[i];
q.push({j, CO[j][w[i] + dist], w[i] + dist});
}
}
}
}
signed main() {
memset(h, -1, sizeof(h));
cin >> st.x >> st.y >> ed.x >> ed.y;
cin >> B >> C[0];
cin >> T;
for (int i = 1; i <= T; i++) {
cin >> C[i];
}
cin >> n;
for (int i = 1, x, y, num; i <= n; i++) {
cin >> x >> y >> num;
pos[i] = {x, y};
for (int j = 1; j <= num; j++) {
cin >> x >> y;
g[i].push_back({x, y});
}
}
pos[0] = st;
pos[n + 1] = ed;
for (int i = 1; i <= n; i++) {
int len = g[i].size();
for (int j = 0; j < len; j++) {
int sta = g[i][j].first, y = g[i][j].second;
sta++;
int dist = cal(pos[i], pos[sta]);
add_edge(i, sta, dist, dist * C[y]);
add_edge(sta, i, dist, dist * C[y]);
}
}
for (int i = 1; i <= n; i++) {
int dist = cal(pos[i], pos[0]);
add_edge(i, 0, dist, dist * C[0]);
add_edge(0, i, dist, dist * C[0]);
dist = cal(pos[i], pos[n + 1]);
add_edge(i, n + 1, dist, dist * C[0]);
add_edge(n + 1, i, dist, dist * C[0]);
}
int dist = cal(pos[0], pos[n + 1]);
add_edge(0, n + 1, dist, dist * C[0]);
add_edge(n + 1, 0, dist, dist * C[0]);
dijkstra();
int res = inf;
for (int i = 0; i <= B; i++) {
res = min(res, CO[n + 1][i]);
}
if (res == inf)
cout << "-1" << endl;
else
cout << res << endl;
}
Icebergs
题意:
求多面形面积的和
思路:
套模板(分割成三角形的思想),求多边形面积,取出的面积记得取绝对值,abs!!!!!!
``
View Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define x first
#define y second
typedef pair<int, int> PII;
const int N = 1111;
PII a[N];
int cross(PII a, PII b) { return a.x * b.y - a.y * b.x; }
int area(PII a, PII b, PII c) {
PII x = {b.x - a.x, b.y - a.y};
PII y = {c.x - a.x, c.y - a.y};
return cross(x, y);
}
signed main() {
int T;
cin >> T;
int res = 0;
while (T--) {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
int x, y;
cin >> x >> y;
a[i] = {x, y};
}
int now = 0;
for (int i = 0; i + 1 < n; i++) {
now += area(a[0], a[i], a[i + 1]);
}
res += abs(now);
}
res = res / 2;
cout << res << endl;
}
Birdwatching
题意:
给定一张有向图,给定一个终点\(v\),问现在有多少个点\(u\),满足所有从\(u\)出发到\(v\)的路径都经过\((u,v)\)
思路:
建立反图,把边反向,对于有边\((u,v)\)的这些点来说,看从终点\(v\)走,到达\(u\)的合法路径数有多少。
但是这种方法对于\(v->u->a->b->u\)这种有环的会误判,会认为\(u\)不合法,因为计数记了\(2\),所以建立反图跑\(BFS\)时,需要建立一个\(fa\)数组,来记录当前点的起点为哪个点,当进入环时,由于已经进入过了,就不会再次重复计数,对于有边\((u,v)\)的这些点,都跑一遍\(BFS\)即可,只要记录的合法路径数\(>1\),说明不符合题意
View Code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int> e[N];
int n, m, s;
vector<int> temp;
vector<int> ans;
int cnt[N];
int fa[N];
void bfs(int u) {
cnt[u]++;
queue<int> q;
q.push(u);
fa[u] = u;
while (q.size()) {
auto t = q.front();
q.pop();
for (auto v : e[t]) {
if (cnt[v] > 1 || v == s || v == u) continue;
if (fa[v] != u) {
fa[v] = u;
q.push(v);
cnt[v] += cnt[t];
}
}
}
}
int main() {
cin >> n >> m >> s;
for (int i = 1, x, y; i <= m; i++) {
cin >> x >> y;
if (y == s) {
temp.push_back(x);
}
e[y].push_back(x);
}
for (auto i : temp) {
bfs(i);
}
for (auto i : temp) {
if (cnt[i] == 1) ans.push_back(i);
}
sort(ans.begin(), ans.end());
cout << ans.size() << endl;
for (auto i : ans) {
cout << i << endl;
}
}

浙公网安备 33010602011771号