A题
题意:小孩子排队领糖, 每个小孩的期望数不一定一样, 每次给第一个孩子发m颗糖,达到期望的孩子离开, 没有的排到最后的位子, 求最后一个孩子的编号
分析:
开一个队列简单模拟即可
B题
题意:给你x1和x2, 公式为xi = xi-1 + xi+1 求xn
分析:打表可得该数列以6为一个周期, 因此可先生成前6项, 对n求余即可
C题
题意:给你一个n*m的方格, 可切k刀, 要求最后最小方格的最大值
分析:简单贪心
我们保证n < m
1 if n+m-2 < k 则答案为-1
2 else n >= k+1 则在全部切在行或全部切在列取最大值
3 else m >= k+1 则全部切在列
4 else 则k-1刀且在列, 剩余的且在行
D题:
题意:给你m条道路和n条铁路,道路连接着两个城市, 双向, 铁路连接着首都和一个城市, 双向, 求最大的铁路减少数, 使得首都到任意城市的最小距离不变
分析:先根据铁路的边权和道路的边权求最小距离, 根据dijkstra。美剧每一条铁路, 如果铁路直达的距离大于最小值, 答案加1 如果铁路直达的距离等于最小距离并且到达该点的方案数大于1, 则答案加1, 同时方案数要减1
贴一下D题代码
#include <queue>
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 ll;
typedef pair<ll, ll> pll;
const ll inf = 1ll << 60;
struct Edge {
ll v, w;
Edge (ll v, ll w) :
v(v), w(w) {}
};
priority_queue <pll, vector<pll>, greater<pll> > q;
vector <Edge> e[100010];
vector <Edge> a;
ll dis[100010], cnt[100010];
bool vis[100010];
int n, m, k;
void dijkstra() {
dis[1] = 0;
cnt[1] = 1;
q.push(make_pair(0, 1));
while(q.size()) {
ll x = q.top().second;
q.pop();
if(vis[x]) continue;
vis[x] = 1;
for(int i=0; i<e[x].size(); i++) {
Edge t = e[x][i];
ll v = t.v;
ll w = t.w;
if(dis[v] > dis[x] + w) {
dis[v] = dis[x] + w;
cnt[v] = cnt[x];
q.push(make_pair(dis[v], v));
}
else if(dis[v] == dis[x] + w) {
cnt[v] += cnt[x];
if(cnt[x] > 1e8) cnt[x] = 1e8;
}
}
}
}
int main() {
scanf("%d%d%d", &n,&m, &k);
for(int i=1; i<=n; i++) {
dis[i] = inf;
vis[i] = 0;
cnt[i] = 0;
}
for(int i=1; i<=m; i++) {
ll u, v, w;
cin >> u >> v >> w;
e[u].push_back(Edge(v, w));
e[v].push_back(Edge(u, w));
}
for(int i=1; i<=k; i++) {
ll u = 1, v, w;
cin >> v >> w;
e[u].push_back(Edge(v, w));
e[v].push_back(Edge(u, w));
a.push_back(Edge(v, w));
}
dijkstra();
int ans = 0;
for(int i=0; i<a.size(); i++) {
ll x = a[i].v;
ll y = a[i].w;
if(y > dis[x]) ans++;
else if(y == dis[x] && cnt[x] > 1) {
cnt[x] --;
ans++;
}
}
printf("%d\n", ans);
return 0;
}