zoukankan      html  css  js  c++  java
  • [黑科技]分层图

    最近几天写了一些分层图的题目,来总结一下

    分层图有一个很重要的性质:上一层不能到达下一层,但下一层能到达上一层

    分层图常常结合最短路,所以叫分层图最短路,当然,也结合缩点之类的

    [USACO09FEB]改造路Revamping Trails

    双倍经验题[JLOI2011]飞行路线

    这是一道分层图最短路裸题

    考虑(dp),(dis[i][j])表示到达第(i)个点已经(j)次升级后所经过的最短路径

    那么就可以愉快的在(Dijkstra)里分类讨论一下

    (Code Below:)

    #include <bits/stdc++.h>
    #define mp make_pair
    #define S second
    #define F first
    using namespace std;
    const int maxn=10000+10;
    const int maxm=50000+10;
    int n,m,k,head[maxn],dis[maxn][21],vis[maxn][21],tot;
    struct node{
        int to,next,val;
    }e[maxm<<1];
    
    inline int read(){
        register int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return (f==1)?x:-x;
    }
    inline void add(int x,int y,int w){
        e[++tot].to=y;
        e[tot].val=w;
        e[tot].next=head[x];
        head[x]=tot;
    }
    void Dijkstra(){
        memset(dis,0x3f3f3f3f,sizeof(dis));
        priority_queue<pair<int,pair<int,int> > > pq;
        pair<int,int> u;int v;
        dis[1][0]=0;pq.push(mp(0,mp(1,0)));
        while(!pq.empty()){
            u=pq.top().S;pq.pop();
            if(vis[u.F][u.S]) continue;
            vis[u.F][u.S]=1;
            for(int i=head[u.F];i;i=e[i].next){
                v=e[i].to;
                if(dis[v][u.S]>dis[u.F][u.S]+e[i].val){
                    dis[v][u.S]=dis[u.F][u.S]+e[i].val;
                    pq.push(mp(-dis[v][u.S],mp(v,u.S)));
                }
                if(u.S+1<=k&&dis[v][u.S+1]>dis[u.F][u.S]){
                    dis[v][u.S+1]=dis[u.F][u.S];
                    pq.push(mp(-dis[v][u.S+1],mp(v,u.S+1)));
                }
            }
        }
    }
    
    
    int main()
    {
        n=read(),m=read(),k=read();
        int x,y,w;
        for(int i=1;i<=m;i++){
            x=read(),y=read(),w=read();
            add(x,y,w);add(y,x,w);
        }
        Dijkstra();
        printf("%d
    ",dis[n][k]);
        return 0;
    }
    

    [USACO15JAN]草鉴定Grass Cownoisseur

    这道题比刚刚那道麻烦一点

    首先看到有环,缩点一下,重新建图。把图复制一遍,将第一层的(to[i])向第二层的(x)连一条边

    (Code Below:)

    #include <bits/stdc++.h>
    #include <time.h>
    #define inf 99999999
    using namespace std;
    const int maxn=100000+10;
    int n,m,low[maxn],dfn[maxn],vis[maxn<<1],tim;
    int head[maxn<<1],to[maxn<<2],nxt[maxn<<2],tot;
    int col[maxn],siz[maxn<<1],color;
    int x[maxn],y[maxn],dis[maxn<<1];
    stack<int> s;
    inline int read(){
        register int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return (f==1)?x:-x;
    }
    inline void add(int x,int y){
        to[++tot]=y;
        nxt[tot]=head[x];
        head[x]=tot;
    }
    void tarjan(int u)
    {
        low[u]=dfn[u]=++tim;
        vis[u]=1;s.push(u);
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i];
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(vis[v]) low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u]){
            color++;
            while(s.top()!=u){
                vis[s.top()]=0;
                col[s.top()]=color;
                siz[color]++;
                s.pop();
            }
            vis[u]=0;col[u]=color;siz[color]++;s.pop();
        }
    }
    
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=m;i++){
            x[i]=read(),y[i]=read();
            add(x[i],y[i]);
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i]) tarjan(i);
        memset(head,0,sizeof(head));
        memset(to,0,sizeof(to));
        memset(nxt,0,sizeof(nxt));
        memset(vis,0,sizeof(vis));
        tot=0;
        for(int i=1;i<=m;i++)
            if(col[x[i]]!=col[y[i]]){
                add(col[x[i]],col[y[i]]);
                add(col[x[i]]+color,col[y[i]]+color);
                add(col[y[i]],col[x[i]]+color);
            }
        for(int i=1;i<=color;i++) siz[i+color]=siz[i];
        queue<int> q;
        vis[col[1]]=1;
        q.push(col[1]);
        while(!q.empty()){
            int u=q.front();q.pop();vis[u]=0;
            for(int i=head[u];i;i=nxt[i]){
                int v=to[i];
                if(dis[v]<dis[u]+siz[u]){
                    dis[v]=dis[u]+siz[u];
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        printf("%d
    ",dis[col[1]+color]);
        return 0;
    }
    
  • 相关阅读:
    kotlin异常类
    kotlin之null值安全性
    kotlin之操作符重载
    kotlin 之相等判断
    Java 的抽象特性:抽象类与接口深度解析
    人人都能够做深度学习应用:入门篇
    HBase源代码分析之HRegionServer上MemStore的flush处理流程(一)
    通讯录结构体方法的实现 和VS中存在的一些问题的分析
    2015爱奇艺暑期实习生面试
    cocos2d-x 源代码分析 : EventDispatcher、EventListener、Event 源代码分析 (新触摸机制,新的NotificationCenter机制)
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/9610084.html
Copyright © 2011-2022 走看看