Xeon第二次训练赛 by洛谷ACM训练营

A.爆炸题    图论,最短路,思维

给出一个图,从1点开始每秒为1米的速度火焰扩展,如果遇到大于一个火焰相遇就会爆炸,问最终爆炸的个数

容易得出以下规律:如果在某个点爆炸,那么这个点存在大于1的入度使得最短路相等   如果在边上爆炸,那么这条边不在最短路上

#include<iostream>
#include<string>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<queue>
#include<stack>
#include<sstream>
#include<cstdio>
#define INF 0x3f3f3f3f
const int maxn = 300000 + 10;
const double PI = acos(-1.0);
typedef long long ll;
using namespace std;

int n, m;

struct edge { int v, w; edge(int a, int b) { v = a, w = b; } };//v终点,w边权

struct node {
    int id, dis;//id点编号 dis暂时距离
    node(int a, int b) { id = a, dis = b; }
    friend bool operator<(node a, node b) {
        return a.dis > b.dis;//每次让距离小出队
    }
};

vector<edge>e[maxn];
int dis[maxn];//记录最短路
bool vis[maxn];//记录是否找到最短路
int ans;

void Dijkstra() {
    int s = 1;//s起点 根据情况改
    for (int i = 0; i <= n; i++)dis[i] = INF, vis[i] = 0;
    dis[s] = 0;
    priority_queue<node>Q;
    Q.push(node(s, 0));
    while (!Q.empty()) {
        node u = Q.top(); Q.pop();
        if (vis[u.id])continue;
        vis[u.id] = 1;
        for (int i = 0; i < e[u.id].size(); i++) {//遍历邻居
            edge y = e[u.id][i];
            if (vis[y.v])continue;
            if (dis[y.v] > y.w + dis[u.id]) {
                dis[y.v] = y.w + u.dis;
                Q.push(node(y.v, dis[y.v]));//更新最短路
            }
        }
    }

}
int main() {
    scanf("%d%d", &n, &m);
    int u, v, w;
    for (int i = 0; i < m; i++) {
        scanf("%d%d%d", &u, &v, &w);
        e[u].push_back(edge(v, w));
        if (u != v) e[v].push_back(edge(u, w));
    }
    Dijkstra();
    //for (int i = 1; i <= n; i++) printf("%d  ", dis[i]);
    for (int i = 1; i <= n; i++) {
        int cnt = 0;
        for (int j = 0; j < e[i].size(); j++) {
            if (dis[i] == dis[e[i][j].v] + e[i][j].w) cnt++;
            else if (i >= e[i][j].v && dis[i] + e[i][j].w > dis[e[i][j].v] && dis[e[i][j].v] + e[i][j].w > dis[i]) ans++;  //core
        }
        if (cnt > 1) ans++;
    }
    printf("%d", ans);
    return 0;
}
View Code

B. 模拟题/公式题

  其实就是给出日期,求过n天后的日期

#include <bits/stdc++.h>
using namespace std;
inline void read(int &a) {
    int ch = getchar();
    while (ch < '0') ch = getchar();
    a = 0;
    while (ch >= '0') a = a * 10 + ch - '0', ch = getchar();
}
int M[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
void work() {
    int Mo, y, m, d;
    read(Mo); read(y); read(m); read(d); 
    int del = 0;
    while (Mo < int(1e9)) {
        del++;
        Mo += del;
        if (++d > M[m] + (m == 2 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))) {
            d = 1;
            if (++m == 13) y ++, m = 1;
        }
    }
    printf("%d %d %d\n", y, m, d);
}

int main() {
    int T; read(T);
    while (T--) work();
    return 0;
}
View Code

C.下次一定

D.给出a,b,k,gcd(a,b)=1 求满足 方程 ax+by=c, ab<0的第k小的c

猜你喜欢

转载自www.cnblogs.com/hznumqf/p/12389225.html