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;
}

 

posted @ 2020-02-23 13:11  wlzs1432  阅读(132)  评论(0编辑  收藏  举报