Java教程

图论--分层图

本文主要是介绍图论--分层图,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

前言:

什么是分层图呢?请自行度娘。

什么时候用呢?当这个图可以改变一些路径的长度,或者一些状态(这个就需要在题目里面体会了)。

但是要注意,分层图对时间和空间的要求很高,所以当k比较小的时候,才可以使用。

分层图的空间一定要算好,不要像我,每次分层图总是空间爆了,或者RE。

先给个模板代码(Luogu4568)

代码:

#include<bits/stdc++.h>
using namespace std;
struct edge
{
    int v,w,nxt;
}e[3001001];
int cnt,head[3001001];
void add(int u,int v,int w)
{
    cnt++;
    e[cnt].v=v;
    e[cnt].w=w;
    e[cnt].nxt=head[u];
    head[u]=cnt;
}
int dis[3001001];
bool vis[3001001];
struct node
{
    int id,dis;
    bool operator < (const node &tt) const
    {
        return dis>tt.dis;
    }
};
priority_queue<node> q;
void dij(int s)
{
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[s]=0;
    q.push(node{s,0});
    while(q.size())
    {
        node uu=q.top();
        int u=uu.id;
        q.pop();
        if(vis[u]) continue ;
        vis[u]=1;
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if(dis[v]>dis[u]+e[i].w)
            {
                dis[v]=dis[u]+e[i].w;
                q.push(node{v,dis[v]});
            }
        }
    }
}
int n,m,k,s,t;
int main()
{
    scanf("%d%d%d%d%d",&n,&m,&k,&s,&t);
    for(int i=0;i<m;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
        for(int j=1;j<=k;j++)
        {
            add(u+(j-1)*n,v+j*n,0);
            add(v+(j-1)*n,u+j*n,0);
            add(u+j*n,v+j*n,w);
            add(v+j*n,u+j*n,w);
        }
    }
    dij(s);
    int ans=INF;
    for(int i=0;i<=k;i++)
    ans=min(ans,dis[n+i*n]);//这个要注意!!!
    cout<<ans;
    return 0;
}

例题.

2939 水题

4822 水题

1948

 

 

讲实话我是用SPFA+二分过去的,但这题很明显可以用分层图。同样的建图,二分,如果e[i].w>x的,那么不能走这条路。最后判断一下,能否走到每一层的终点。如果不是用分层图,那就是如果这条路能走,那么w=0,否则为1,最后将cn[n]与k比较,从而得出,能否到达终点,分层图也可以这样,就是最后的判断改一下而已。

1073【NOIP2009】提高组

 

 很多人是缩点加SPFA,反正我不会,商人肯定是先去到自己要买的地方,再想办法去自己要卖的地方,最后去终点,并不是最短路,也就是有三种状态,那么建三层图。

如果从第一层下来,说明在此买了,如果从第二层下来,说明卖了,除了层之间的边,其余边为0,最后求最大值。

这个题这个做法还是很精妙的。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int INF=10000000; 
int n, m, dis[maxn*3], vis[maxn*3];
vector<pair<int, int> > G[maxn*3];
#define t(x,i) (x+i*n) 
#define add(x, y) G[t(x,0)].push_back({t(y,0), 0}), G[t(x,1)].push_back({t(y,1),0}), G[t(x,2)].push_back({t(y,2),0})
void spfa(int s) 
{
    for(int i = 1;i <= n*3;i++) dis[i] =-INF;
    dis[s] = 0; 
    queue<int> q; 
    vis[s]=1; 
    q.push(s);
    while(!q.empty()) 
    {
        int x = q.front();
        q.pop(); 
        vis[x] = 0;
        for(int i=0;i<G[x].size();i++) 
        {
            int v=G[x][i].first;
            if(dis[v] < dis[x] + G[x][i].second) 
            {
                dis[v] = dis[x] + G[x][i].second;
                if(!vis[v]) { q.push(v); vis[v] = 1; }
            } 
        }
    }
}

int main() 
{
    cin >> n >> m;
    for(int i = 1, v;i <= n; ++i) {
        cin >> v;
        G[t(i,0)].push_back({t(i,1), -v});
        G[t(i,1)].push_back({t(i,2), v});
    }
    for(int i = 1,x,y,z;i <= m; ++i) 
    {
        cin >> x >> y >> z; 
        add(x, y);
        if(z == 2) add(y, x);
    }
    spfa(t(1,0));
    cout << dis[t(n,2)] << endl;
    return 0;
}

 

这篇关于图论--分层图的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!