分层图题目

P9504 『MGOI』Simple Round I | C. 魔法禁林

Link
\(w \leqslant 100\) ,当 \(k>100\) 时,\(\lfloor\frac{n}{k}\rfloor\) 始终为 \(0\)
\(\lfloor\frac{n}{k}\rfloor\) 为层数建图。

#include <iostream>
#include <queue>
#include <cmath>
#define MAXN 80010
#define MA 105
using namespace std;
const int inf = 2147483647;
int n,m,s,t,cnt;
int dis[MAXN][105],h[MAXN],to[MAXN],val[MAXN],nxt[MAXN];
bool vis[MAXN][105];
int maxw;
struct node {
    int v,w,k;
     friend bool operator < (node a,node b) {
        return a.w > b.w;
    }
} tmp;
priority_queue <node> q;
void add(int a,int b,int c) {
    to[++cnt] = b;
    val[cnt] = c;
    nxt[cnt] = h[a];
    h[a] = cnt;
}
void dijkstra() {
    for(int i = 1;i <= n;++ i)
        for(int j = 0;j <= 101;++ j)
            dis[i][j] = inf;
    dis[s][0] = 0;
    tmp.v = s;tmp.w = 0;tmp.k = 0;q.push(tmp);
    while(!q.empty()) {
        int u = q.top().v,k = q.top().k;
        q.pop();
        if(vis[u][k]) continue;
        vis[u][k] = 1;
        for(int i = h[u];i;i = nxt[i]) {
            if(dis[to[i]][min(101,k + 1)] > (long long)dis[u][min(101,k)] + val[i] / (k + 1)) {
                dis[to[i]][min(101,k + 1)] = dis[u][min(101,k)] + val[i] / (k + 1);
                tmp.k = k + 1;
                tmp.w = dis[to[i]][min(101,k + 1)];
                tmp.v = to[i];
                q.push(tmp);
            }
        }
    }
}
int main() {
    cin >> n >> m >> s >> t;
    swap(s,t);
    int u,v,w;
    for(int i = 1;i <= m;++ i) {
        cin >> u >> v >> w;
        add(u,v,w);
        add(v,u,w);
        maxw = max(maxw,w);
    }
    dijkstra();
    int minn = inf;
    for(int i = 0;i <= 100;++ i) minn = min(minn,dis[t][i]);
    cout << minn;
    return 0;
}

P1073 [NOIP2009 提高组] 最优贸易

Link
建三层图。
购入是到第二层图,卖出时到第三层图。
每层之间的长度为该点的价格,每层中点之间的路径长度为 \(0\)
因为存在负边权,不能使用 dijkstra ,应使用 spfa 。

#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
#define MAXN 100005
#define MAXM 500005
#define inf 2147483647
int n,m,h[MAXN * 3],val[MAXM * 5],nxt[MAXM * 5],cnt,c[MAXN],to[MAXM * 5],dis[MAXN * 3];
bool vis[MAXN * 3];
queue <int> q;
void add(int x,int y,int z) {
    nxt[++cnt] = h[x];
    val[cnt] = z;
    to[cnt] = y;
    h[x] = cnt;
}
void spfa() {
    for(int i = 1;i <= n * 3;++ i) dis[i] = -inf;
    dis[1] = 0;
    q.push(1);
    while(!q.empty()) {
        int u =  q.front();
        q.pop();
        vis[u] = false;
        for(int i = h[u];i;i = nxt[i]) {
            if(dis[to[i]] < dis[u] + val[i]) {
                dis[to[i]] = dis[u] + val[i];
                if(!vis[to[i]]) {q.push(to[i]);vis[to[i]] = true;}
            }
        }
    }
    return ;
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;++ i) scanf("%d",&c[i]);
    for(int x,y,z,i = 1;i <= m;++ i) {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,0);
        add(x + n,y + n,0);
        add(x + n * 2,y + n * 2,0);
        if(z == 2) {
            add(y,x,0);
            add(y + n,x + n,0);
            add(y + n * 2,x + n * 2,0);
        }
    }
    for(int i = 1;i <= n;++ i) {
        add(i,i + n,-c[i]);
        add(i + n,i + n * 2,c[i]);
    }
   spfa();
    cout << max(0,dis[n * 3]);
    return 0;
}

P4568 [JLOI2011] 飞行路线

Link
\(k\) 层,每层之间用 \(0\) 连接。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
#define MAXN 100005
#define MAXM 500004
#define inf 2147483647
int s,t,n,m,k,cnt;
int h[MAXN * 10],dis[MAXN * 10];
bool v[MAXN * 10];
struct edge {
    int val;
    int to;
    int nxt;
} e[MAXM * 10];
struct node {
    int val;
    int id;
    bool friend operator < (node a,node b) {
        return a.val > b.val;
    }
} tmp;
priority_queue <node> q;
void add(int x,int y,int z) {
    e[++cnt].val = z;
    e[cnt].to = y;
    e[cnt].nxt = h[x];
    h[x] = cnt;
}
void dijkstra() {
    for(int i = 0;i <= n * k + n;++ i) dis[i] = inf;
    dis[s] = 0;
    tmp.val = 0;tmp.id = s;
    q.push(tmp);
    while(!q.empty()) {
        int u = q.top().id;
        q.pop();
        if(v[u]) continue;
        v[u] = true;
        for(int i = h[u];i;i = e[i].nxt) {
            if(dis[u] + e[i].val < dis[e[i].to]) {
                dis[e[i].to] = dis[u] + e[i].val;
                tmp.val = dis[e[i].to];tmp.id = e[i].to;
                q.push(tmp);
            }
        }
    }
    return ;
}
int main() {
    scanf("%d%d%d",&n,&m,&k);
    scanf("%d%d",&s,&t);
    for(int i = 1,x,y,z;i <= m;++ i) {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
        for(int j = 1;j <= k;++ j) {
            add(x + j * n - n,y + j * n,0);
            add(y + j * n - n,x + j * n,0);
            add(x + j * n,y + j * n,z);
            add(y + j * n,x + j * n,z);
        }
    }
    dijkstra();
    int ans = inf;
    for(int i = 0;i <= k;++ i) ans = min(ans,dis[t + i * n]);
    cout << ans;
    return 0;
}

P2939 [USACO09FEB] Revamping Trails G

Link
同上。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
#define MAXN 100005
#define MAXM 500004
#define inf 2147483647
int s,t,n,m,k,cnt;
int h[MAXN * 10],dis[MAXN * 10];
bool v[MAXN * 10];
struct edge {
    int val;
    int to;
    int nxt;
} e[MAXM * 10];
struct node {
    int val;
    int id;
    bool friend operator < (node a,node b) {
        return a.val > b.val;
    }
} tmp;
priority_queue <node> q;
void add(int x,int y,int z) {
    e[++cnt].val = z;
    e[cnt].to = y;
    e[cnt].nxt = h[x];
    h[x] = cnt;
}
void dijkstra() {
    for(int i = 0;i <= n * k + n;++ i) dis[i] = inf;
    dis[s] = 0;
    tmp.val = 0;tmp.id = s;
    q.push(tmp);
    while(!q.empty()) {
        int u = q.top().id;
        q.pop();
        if(v[u]) continue;
        v[u] = true;
        for(int i = h[u];i;i = e[i].nxt) {
            if(dis[u] + e[i].val < dis[e[i].to]) {
                dis[e[i].to] = dis[u] + e[i].val;
                tmp.val = dis[e[i].to];tmp.id = e[i].to;
                q.push(tmp);
            }
        }
    }
    return ;
}
int main() {
    scanf("%d%d%d",&n,&m,&k);
    for(int i = 1,x,y,z;i <= m;++ i) {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
        for(int j = 1;j <= k;++ j) {
            add(x + j * n - n,y + j * n,0);
            add(y + j * n - n,x + j * n,0);
            add(x + j * n,y + j * n,z);
            add(y + j * n,x + j * n,z);
        }
    }
    s = 1;t = n;
    dijkstra();
    int ans = inf;
    for(int i = 0;i <= k;++ i) ans = min(ans,dis[t + i * n]);
    cout << ans;
    return 0;
}

P4822 [BJWC2012] 冻结

Link
同上。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
#define MAXN 100005
#define MAXM 500004
#define inf 2147483647
int s,t,n,m,k,cnt;
int h[MAXN * 10],dis[MAXN * 10];
bool v[MAXN * 10];
struct edge {
    int val;
    int to;
    int nxt;
} e[MAXM * 10];
struct node {
    int val;
    int id;
    bool friend operator < (node a,node b) {
        return a.val > b.val;
    }
} tmp;
priority_queue <node> q;
void add(int x,int y,int z) {
    e[++cnt].val = z;
    e[cnt].to = y;
    e[cnt].nxt = h[x];
    h[x] = cnt;
}
void dijkstra() {
    for(int i = 0;i <= n * k + n;++ i) dis[i] = inf;
    dis[s] = 0;
    tmp.val = 0;tmp.id = s;
    q.push(tmp);
    while(!q.empty()) {
        int u = q.top().id;
        q.pop();
        if(v[u]) continue;
        v[u] = true;
        for(int i = h[u];i;i = e[i].nxt) {
            if(dis[u] + e[i].val < dis[e[i].to]) {
                dis[e[i].to] = dis[u] + e[i].val;
                tmp.val = dis[e[i].to];tmp.id = e[i].to;
                q.push(tmp);
            }
        }
    }
    return ;
}
int main() {
    scanf("%d%d%d",&n,&m,&k);
    for(int i = 1,x,y,z;i <= m;++ i) {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
        for(int j = 1;j <= k;++ j) {
            add(x + j * n - n,y + j * n,z / 2);
            add(y + j * n - n,x + j * n,z / 2);
            add(x + j * n,y + j * n,z);
            add(y + j * n,x + j * n,z);
        }
    }
    s = 1;t = n;
    dijkstra();
    int ans = inf;
    for(int i = 0;i <= k;++ i) ans = min(ans,dis[t + i * n]);
    cout << ans;
    return 0;
}
posted @ 2023-08-10 11:54  eegg  阅读(32)  评论(0)    收藏  举报