• LuoguP2685 [TJOI2012]桥


    LuoguP2685 [TJOI2012]桥

    题意

    链接

    题解

    原题可以转化成在图上每次删一条边后求最短路

    考虑先找到一条最短路

    那么每次删掉的边有两种情况:

    如果这条边不在最短路上那么答案不变

    如果在最短路上

    显然这条边会被一个不在最短路上的路径代替,考虑枚举这样一条不在最短路上的边 u -> v

    假如这条边在新的最短路上,那么现在的最短路就是 1 -> a - > u - > v - > b - > n

    显然要让这条路径尽量小 ,a 点就应该是1 - > n 的最短路 与 1 - > u 的最短路 的分界处,同理 b 也是

    那么在 a 与 b 点间被删的边都可能被这条路径代替,原问题就变成了一道区间最值问题

    线段树解决

    #include<bits/stdc++.h>
    
    #define LL long long
    
    using namespace std;
    
    inline LL read()
    {
        LL f = 1 , x = 0;
        char ch;
        do
        {
            ch = getchar();
            if(ch=='-') f=-1;
        } while(ch<'0'||ch>'9');
        do
        {
            x=(x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }while(ch>='0'&&ch<='9');
        return f*x;
    }
    
    const int MAXN = 4e5 + 10;
    const int MAXM = 4e5 + 10;
    const long long INF = 1LL << 62;
    
    int n,m,s,t;
    
    struct node
    {
        int to;
        int ne;
        long long val;
        int from;
    }g[MAXM << 1],G[MAXN << 1],e[MAXN];
    int cnt,head[MAXN];
    int cnt1,Head[MAXN];
    int pre[MAXN];
    int path[MAXN],tot;
    int d[MAXN];
    
    inline void addedge(int u,int v,long long w)
    {
        ++cnt;g[cnt].from=u;g[cnt].to=v;g[cnt].ne=head[u];g[cnt].val=w;head[u]=cnt;return;
    }
    
    inline void addedge1(int u,int v)
    {
        ++cnt1;pre[v]=u;G[cnt1].from = u;G[cnt1].to = v;d[v]++;G[cnt1].ne = Head[u];Head[u]=cnt1;return;
    }
    
    struct Heap
    {
        int u;
        LL val;
        friend bool operator < (Heap a1,Heap a2)
        {
            return a1.val>a2.val;
        }
    };
    
    priority_queue<Heap>pq;
    long long dis1[MAXN];
    long long dis2[MAXN];
     
    inline Heap makenode(int a,long long b)
    {
         Heap u;
        u.u = a;
        u.val = b;
        return u;     
    } 
     
    inline void Dij1()
    {
        for(int i=1;i<=n;i++) dis1[i] = INF;
        dis1[s] = 0;
        pq.push(makenode(s,0));
        while(pq.size())
        {
            long long u = pq.top().u,disu = pq.top().val;
            pq.pop();
            if(disu != dis1[u]) continue;
            for(int i=head[u];i;i=g[i].ne)
            {
                int v = g[i].to;
                if(dis1[v] > dis1[u] + g[i].val)
                {
                    dis1[v] = dis1[u] + g[i].val;
                //    pre[v] = u;
                    pq.push(makenode(v,dis1[v]));
                }
            }
        }
        return;
    }
    
    int dp1[MAXN],id[MAXN],id2[MAXN];
    bool vis[MAXN];
    
    inline void DP1()
    {
        for(int i=1;i<=m;i++) 
        {
            if(dis1[e[i].from] + e[i].val == dis1[e[i].to]) addedge1(e[i].from,e[i].to),vis[i]=1;
            if(dis1[e[i].to] + e[i].val == dis1[e[i].from]) addedge1(e[i].to,e[i].from),vis[i]=1;
        }
        for(int i=t;i!=s;i=pre[i]) path[++tot] = i;path[++tot] = s;
        reverse(path+1,path+tot+1);
        for(int i=1;i<=tot;i++) id[path[i]] = i,id2[i]=path[i];
        for(int i=1;i<=n;i++) dp1[i] = MAXN;
        for(int i=1;i<=tot;i++) dp1[path[i]] = i;
        queue<int>q;q.push(s);
        while(q.size())
        {
            int u = q.front();q.pop();
            for(int i=Head[u];i;i=G[i].ne)
            {
                int v = G[i].to;
                if(!id[v]) dp1[v] = min(dp1[v],dp1[u]);
                d[v]--;
                if(!d[v]) q.push(v);
            }
        }
    }
    
    inline void Dij2()
    {
        for(int i=1;i<=n;i++) dis2[i] = INF;
        dis2[t] = 0;
        pq.push(makenode(t,0));
        while(pq.size())
        {
            long long u = pq.top().u,disu = pq.top().val;
            pq.pop();
            if(disu != dis2[u]) continue;
            for(int i=head[u];i;i=g[i].ne)
            {
                int v = g[i].to;
                if(dis2[v] > dis2[u] + g[i].val)
                {
                    dis2[v] = dis2[u] + g[i].val;
                    pq.push(makenode(v,dis2[v]));
                }
            }
        }
        return;
    }
    
    inline void Clear_Edge()
    {
        cnt1 = 0;
        memset(Head,0,sizeof(Head));
        memset(d,0,sizeof(d));
    }
    
    int dp2[MAXN];
    
    inline void DP2()
    {
        Clear_Edge();
        for(int i=1;i<=m;i++) 
        {
            if(dis2[e[i].from] + e[i].val == dis2[e[i].to]) addedge1(e[i].from,e[i].to);
            if(dis2[e[i].to] + e[i].val == dis2[e[i].from]) addedge1(e[i].to,e[i].from);
        }
        for(int i=1;i<=tot;i++) dp2[path[i]] = i;
    //    for(int i=1;i<=n;i++) cout << dp2[i] << " ";
    //    cout << endl;
        queue<int>q;q.push(t);
        while(q.size())
        {
            int u = q.front();q.pop();
            for(int i=Head[u];i;i=G[i].ne)
            {
                int v = G[i].to;
                if(!id[v]) dp2[v] = max(dp2[v],dp2[u]);
                d[v]--;
                if(!d[v]) q.push(v);
            }
        }
    }
    
    #define lc o<<1
    #define rc o<<1|1
    
    long long tr[MAXN<<2];
    
    inline void build(int o,int l,int r)
    {
        if(l == r) 
        {
            tr[o] = INF;
            return;
        }
        int mid = (l+r)>>1;
        build(lc,l,mid);
        build(rc,mid+1,r);
        tr[o] = INF;
    }
    
    inline int check(int x,int y)
    {
        if(!id[x]) return false;
        if(!id[y]) return false;
        if(id[y] == id[x] + 1) return id[x];
        if(id[x] == id[y] + 1) return id[y];
        return false; 
    }
    
    inline void update(int o,int l,int r,int x,int y,long long v)
    {
        if(x<=l&&r<=y) 
        {
            tr[o] = min(tr[o],v);
            return;
        }
    //    if(l>y||x>r) return;
        int mid = (l+r)>>1;
        if(x<=mid)
        update(lc,l,mid,x,y,v);
        if(y>mid)
        update(rc,mid+1,r,x,y,v);
    //    tr[o] = min(tr[lc],tr[rc]);
    }
    
    long long ans[MAXN];
    
    inline void get(int o,int l,int r)
    {
        if(l == r)
        {
            ans[l] = tr[o];
            return;
        }
        int mid = (l+r)>>1;
        tr[lc] = min(tr[lc],tr[o]);    get(lc,l,mid);
        tr[rc] = min(tr[rc],tr[o]);get(rc,mid+1,r);
    }
    
    int main()
    {
        n = read(),m = read();
        s = 1,t = n;
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            e[i].from = u =  read(),e[i].to = v =  read(),e[i].val = w = read();
            addedge(u,v,w);
            addedge(v,u,w);
        }
        Dij1();
        DP1();
        Dij2();    
        DP2();
        build(1,1,tot-1);
    //    cout << tr[1] << endl;
    //    cout <<tot << endl; 
    //    for(int i=1;i<=n;i++) cout << dis1[i] << " " << dis2[i] << endl;
        for(int i=1;i<=m;i++)
        {
            int u = e[i].from , v = e[i].to;
            //if(check(u,v)) continue;
            if(vis[i]) continue;
        //    cout << u << " " << v << " "<< dp1[u] <<" " << dp2[v] << " "<<e[i].val+dis1[u]+dis2[v]<<endl;
        //    cout << v << " " << u << " "<< dp1[v] <<" " << dp2[u] << " "<<e[i].val+dis1[v]+dis2[u]<<endl;
            if(dp1[u]<MAXN&&dp2[v]&&dp1[u]<dp2[v]) update(1,1,tot-1,dp1[u],dp2[v]-1,e[i].val + dis1[u] + dis2[v]);
            if(dp1[v]<MAXN&&dp2[u]&&dp1[v]<dp2[u]) update(1,1,tot-1,dp1[v],dp2[u]-1,e[i].val + dis1[v] + dis2[u]); 
        //    cout << tr[1] << endl;
        }
    //    cout << dis1[t] << endl;
        get(1,1,tot-1);
        long long maxcost = 0;
        for(int i=1;i<tot;i++)
        {
            //cout << ans[i] << " ";
            maxcost = max(maxcost,ans[i]);
        }
        int total = 0;
        for(int i=1;i<tot;i++)
        {
            if(maxcost==ans[i]) total++;
        }
        cout << maxcost << " " <<total << endl;
        return 0;
    }
  • 相关阅读:
    servletContext
    解决Response输出时乱码
    servletConfig
    服务器和浏览器交互过程
    myeclipse配置
    servlet
    http协议
    配置虚拟主机
    配置主页
    开网站步骤
  • 原文地址:https://www.cnblogs.com/wlzs1432/p/12074294.html
Copyright © 2020-2023  润新知