Educational Codeforces Round 102 (Rated for Div. 2)

题目:E. Minimum Path

分析:

这个题首先是最短路问题。
只保留公式的第一项的话,就是最朴素的最短路问题。
现在加了两项,很显然是最短路的变形。
现在我们可以定义最短路为:总路径长度必须删除一条边的权值、添加一条边的权值。
这样我们可以将原来的一维dis数组升为3维,dis[i][j][k],j表示是否删除了一条边,k表示是否添加了一条边。
dis[i][1][1]就是最终我们要求的

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;//三年竞赛一场空,不开long long见祖宗
//typedef __int128 lll;
#define print(i) cout << "debug: " << i << endl
#define close() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mem(a, b) memset(a, b, sizeof(a))
#define pb(a) push_back(a)
#define x first
#define y second
typedef pair<int, int> pii;
const ll mod = 1e9 + 7;
const int maxn = 2e5 + 10;
const int inf = 0x3f3f3f3f;
struct edge
{
    int ep;
    ll val;
    int nex;
}e[maxn << 1];
int head[maxn], tot;
void init(){
    mem(head, -1), tot = 0;
}

void addedge(int x, int y, ll val)
{
    e[tot] = edge{y, val, head[x]};
    head[x] = tot++;
}

struct node
{
    int u;
    ll dis;
    int flag1, flag2;
    bool operator< (const node& b) const
    {
        return b.dis < dis;
    }
};
ll dis[maxn][2][2];
int vis[maxn][2][2];

void dj()
{
    mem(dis, 0x3f);
    mem(vis, 0);
    priority_queue<node> q;
    q.push(node{1, 0, 0, 0});
    dis[1][0][0] = 0;
    while(!q.empty())
    {
        node now = q.top(); q.pop();
        int u = now.u, flag1 = now.flag1, flag2 = now.flag2;
        ll nowdis = now.dis;
        if(vis[u][flag1][flag2]) continue;
        vis[u][flag1][flag2] = 1;
        for(int i = head[u]; ~i; i = e[i].nex)
        {
            int ep = e[i].ep;
            if(dis[ep][flag1][flag2] > nowdis + e[i].val)
                dis[ep][flag1][flag2] = nowdis + e[i].val, q.push(node{ep, dis[ep][flag1][flag2], flag1, flag2});
            if(!flag1 && dis[ep][1][flag2] > nowdis)
                dis[ep][1][flag2] = nowdis, q.push(node{ep, dis[ep][1][flag2], 1, flag2});
            if(!flag2 && dis[ep][flag1][1] > nowdis + 2 * e[i].val)
                dis[ep][flag1][1] = nowdis + 2 * e[i].val, q.push(node{ep, dis[ep][flag1][1], flag1, 1});
            if(!flag1 && !flag2 && dis[ep][1][1] > nowdis + e[i].val)
                dis[ep][1][1] = nowdis + e[i].val, q.push(node{ep, dis[ep][1][1], 1, 1});
        }
    }

}


int main()
{
    init();
    int n, m; cin >> n >> m;
    for(int i = 1; i <= m; i++)
    {
        int x, y;
        ll val; 
        cin >> x >> y >> val;
        addedge(x, y, val), addedge(y, x, val);
    }
    dj();
    for(int i = 2; i <= n; i++)
        printf("%lld%c", dis[i][1][1], i == n ? '\n' : ' ');
}

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页