ACM 实验室2020.10.03天梯赛练习*1

7-13 垃圾箱分布

题意:n个点,m个能当作起始点,k条边,起始点不能与n个点距离超过ds,求到n个点的最短距离最长的起始点

思路:跑m遍dijkstra即可,练习的时候时间不够没写完

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int maxn = 1000 + 15;
const double eps = 1e-9;

int n, m, k, ds;
vector<PII> v[maxn];
int dis[maxn];
bool vis[maxn];
priority_queue<PII, vector<PII>, greater<> > que;

int dijkstra(int x) {
    memset(vis, false, sizeof(vis));
    memset(dis, 0x3f, sizeof dis);
    dis[x] = 0;
    que.push(PII(0, x));
    while (!que.empty()) {
        int point = que.top().second;
        que.pop();
        if (vis[point])
            continue;
        vis[point] = true;
        for (auto i:v[point]) {
            if (dis[i.first] > dis[point] + i.second) {
                dis[i.first] = dis[point] + i.second;
                que.push(PII(dis[i.first], i.first));
            }
        }
    }
    int minn = 0x3f3f3f3f;
    for (int i = 1; i <= n; i++) {
        if (dis[i] > ds)
            return 0x3f3f3f3f;
        minn = min(minn, dis[i]);
    }
    return minn;
}

int main() {
    cin >> n >> m >> k >> ds;
    getchar();
    for (int i = 0; i < k; i++) {
        char s;
        int a = 0, b = 0, c;
        scanf("%c", &s);
        if (s == 'G') {
            cin >> a;
            a += 1000;
            getchar();
        } else {
            while (s != ' ') {
                a *= 10;
                a += s - '0';
                scanf("%c", &s);
            }
        }
        scanf("%c", &s);
        if (s == 'G') {
            cin >> b;
            b += 1000;
            getchar();
        } else {
            while (s != ' ') {
                b *= 10;
                b += s - '0';
                scanf("%c", &s);
            }
        }
        cin >> c;
        getchar();
        v[a].push_back(PII(b, c));
        v[b].push_back(PII(a, c));
    }
    int point = 0;
    int ansmin = -1;
    int ansavg = 0x3f3f3f3f;
    for (int i = 1001; i <= 1000 + m; i++) {
        double minn = dijkstra(i);
        if (minn == 0x3f3f3f3f)
            continue;
        if (ansmin < minn) {
            ansmin = minn;
            int avg = 0;
            for (int j = 1; j <= n; j++)
                avg += dis[j];
            ansavg = avg;
            point = i;
        } else if (minn == ansmin) {
            int avg = 0;
            for (int j = 1; j <= n; j++)
                avg += dis[j];
            if (ansavg > avg) {
                ansavg = avg;
                point = i;
            }
        }
    }

    if (point != 0) {
        cout << "G" << point - 1000 << endl;
        printf("%.1lf %.1lf\n", ansmin * 1.0, ansavg / (double) n);
    } else
        cout << "No Solution" << endl;
    return 0;
}

  

7-15 地铁一日游

题意:n个点m段线路k为为计费距离限制,给m段线路后,q次询问,每次从x站出发,求能拍照的站点

思路:题目吧啦了一堆,无非是要说以下条件:

    选某个车费中最远的(比如说,我花5块钱能到3个地方,那么选最远的)

                                路线的端点(注意!这里是指连通路线的端点)

    用Floyed求最短路,每个站点都找到能拍照的站点,对每次查询都dfs一遍。

    靠蒙和猜题意,慢慢写

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int maxn = 200 + 5;
const double eps = 1e-9;

struct point {
    int vis = 0;
    int ends = 0;
    vector<int> res;
} points[maxn];
int n, m, k;
int mp[maxn][maxn];

void floyed() {
    for (int K = 1; K <= n; K++)
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                if (i != j && mp[i][j] > mp[i][K] + mp[K][j])
                    mp[i][j] = mp[i][K] + mp[K][j];
}

void dfs(int x, int vis) {
    for (int i = 0; i < points[x].res.size(); i++) {
        int tmp = points[x].res[i];
        if (points[tmp].vis != vis) {
            points[tmp].vis = vis;
            dfs(tmp, vis);
        }
    }
}

int main() {
    memset(mp, 0x3f, sizeof mp);
    cin >> n >> m >> k;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u;
        points[u].ends = 1;
        do {
            cin >> w >> v;
            if (w < mp[u][v]) {
                mp[u][v] = w;
                mp[v][u] = w;
            }
            u = v;
        } while (getchar() != '\n');
        points[u].ends = 1;
    }
    floyed();
    for (int i = 1; i <= n; i++) {
        map<int, int> mp1;
        for (int j = 1; j <= n; j++)
            if (mp[i][j] != 0x3f3f3f3f && mp[i][j] > mp1[mp[i][j] / k + 2])
                mp1[mp[i][j] / k + 2] = mp[i][j];
        for (int j = 1; j <= n; j++)
            if (mp[i][j] == mp1[mp[i][j] / k + 2] || (i != j && mp[i][j] != 0x3f3f3f3f && points[j].ends == 1))
                points[i].res.push_back(j);
    }
    int q;
    cin >> q;
    for (int i = 1; i <= q; i++) {
        int start;
        cin >> start;
        points[start].vis = i;
        dfs(start, i);
        int first = true;
        for (int j = 1; j <= n; j++)
            if (points[j].vis == i) {
                if (!first)
                    cout << " ";
                first = false;
                cout << j;
            }
        cout << endl;
    }
    return 0;
}

  

posted @ 2020-10-04 10:24  Whiteying  阅读(140)  评论(0编辑  收藏  举报