CodeForces 360E Levko and Game(Codeforces Round #210 (Div. 1))

题意:有一些无向边m条权值是给定的k条权值在[l,r]区间可以由你来定,一个点s1 出发一个从s2出发  问s1 出发的能不能先打到f

思路:最短路。

首先检测能不能赢 在更新的时候  如果对于一条边 a->b  如果dis1[a] <dis2[a]  那么选择这条边就选择   l  因为这条边对于s1有利 如果两个起点都选择了这条边  则说明s1 赢定了,所以要让他们尽量走这条,所以边权越小越好。跑完之后检测 如果  dis1[f]<dis2[f] 那么 就赢了。

  接下来判断能不能平局。因为目前已经没有赢的可能了  那么  把dis1[a]<dis2[a]改成dis1[a]<=dis2[a] 选择l  其他选择r 即可。原因:小于的话毫无疑问就是选择l  ;等于的话选择小的如果两个都走了这条边则平局。

#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include <iostream>
#include<vector>
#include<queue>
#define INF 1e15
#define LL long long
#define P pair<LL,int>
#define MP make_pair
#define M 200000
#define N 100000
using namespace std;
priority_queue<P> q;
struct node {
    int l, r, to, nx;
} e[M];
int head[N];
int ecnt;
int ans[N];
void addedge(int x, int y, int l, int r) {
    e[ecnt].l = l;
    e[ecnt].r = r;
    e[ecnt].to = y;
    e[ecnt].nx = head[x];
    head[x] = ecnt++;
}
LL d1[N], d2[N];
int n, m, k, s1, s2, f;
void gao(int bo) {
    while (!q.empty())
        q.pop();
    memset(ans, -1, sizeof(ans));
    for (int i = 0; i <= n; ++i)
        d1[i] = d2[i] = INF;
    d1[s1] = d2[s2] = 0;
    q.push(MP(0, s1));
    q.push(MP(0, s2));
    while (!q.empty()) {
        P ee = q.top();
        q.pop();
        LL va = -ee.first;
        int id = ee.second;
        if (va > d1[id] && va > d2[id])
            continue;
        bool ok;
        if (bo == 1) {
            if (d1[id] < d2[id])
                ok = true;
            else
                ok = false;
        } else {
            if (d1[id] <= d2[id])
                ok = true;
            else
                ok = false;
        }
        for (int i = head[id]; i != -1; i = e[i].nx) {
            int u = e[i].to;
            LL add;
            if (ok)
                add = e[i].l;
            else
                add = e[i].r;
            ans[i] = add;
            if (d1[u] > d1[id] + add) {
                d1[u] = d1[id] + add;
                q.push(MP(-d1[u], u));
            }
            if (d2[u] > d2[id] + add) {
                d2[u] = d2[id] + add;
                q.push(MP(-d2[u], u));
            }
        }
    }
}
int main() {
    scanf("%d%d%d", &n, &m, &k);
    scanf("%d%d%d", &s1, &s2, &f);
    memset(head, -1, sizeof(head));
    ecnt = 0;
    for (int i = 0; i < m; ++i) {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        addedge(x, y, z, z);
    }
    for (int i = 0; i < k; ++i) {
        int x, y, l, r;
        scanf("%d%d%d%d", &x, &y, &l, &r);
        addedge(x, y, l, r);
    }
    gao(1);
    if (d1[f] < d2[f]) {
        puts("WIN");
        for (int i = m; i < m + k; ++i) {
            if (ans[i] == -1)
                ans[i] = e[i].l;
            printf("%d", ans[i]);
            if (i == m + k - 1)
                puts("");
            else
                printf(" ");
        }
        return 0;
    }
    gao(0);
    if (d1[f] == d2[f]) {
        puts("DRAW");
        for (int i = m; i < m + k; ++i) {
            if (ans[i] == -1)
                ans[i] = e[i].l;
            printf("%d", ans[i]);
            if (i == m + k - 1)
                puts("");
            else
                printf(" ");
        }
        return 0;
    }
    puts("LOSE");
    return 0;
}

 

转载于:https://www.cnblogs.com/L-Ecry/p/3889101.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值