• P2685 [TJOI2012]桥


    Debug一下午,没想到把n写成m,出锅了。。。

    题意:1-n带权无向图,求删掉一条边使之后的最短路最长,输出这个值并输出删边的方案数

    正解:先跑两遍dij,然后把最短路的边标记,考虑最短路1---s------t-----n

       存在1----s-----x----y----t----n 删掉s---t(因为还要走最短路),所以要维护s---t的最小值(不经过s---t)

       因此可以用线段树,

       先bfs求出lr,(x:l=s,r=t )

       把1-----s------x------y------t------n的长度放在线段树上维护

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define int long long
    #define olinr return
    #define _ 0
    #define DB double
    inline int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                f=-f;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    inline void put(int x)
    {
        if(x<0)
        {
            x=-x;
            putchar('-');
        }
        if(x>9)
            put(x/10);
        putchar(x%10+'0');
    }
    struct node
    {
        node *nxt;
        int to;
        int dis;
        bool vis;
        node()
        {
            nxt=NULL;
            to=dis=vis=0;
        }
    };
    struct tree
    {
        tree *ls;
        tree *rs;
        int l;
        int r;
        int dat;
        tree()
        {
            dat=l=r=0;
            ls=rs=NULL;
        }
    };
    typedef node* nod;
    typedef tree* tre;
    nod head[105050];
    int n;
    int m;
    int diss[105050];
    int dist[105050];
    bool vis[105050];
    int L[105050];
    int R[105050];
    int st[105050];
    int ans[105050];
    int cnt;
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
    queue<int>p;
    inline void add(int from,int to,int dis)
    {
        nod t=new node();
        t->to=to;
        t->dis=dis;
        t->nxt=head[from];
        head[from]=t;
    }
    inline void dij(int s,int *dis)
    {
        dis[s]=0;
        q.push(make_pair(dis[s],s));
        while(!q.empty())
        {
            int tp=q.top().second;
            q.pop();
            if(vis[tp]) continue;
            vis[tp]=true;
            for(nod i=head[tp];i;i=i->nxt)
            {
                if(dis[i->to]>dis[tp]+i->dis)
                {
                    dis[i->to]=dis[tp]+i->dis;
                    q.push(make_pair(dis[i->to],i->to));
                }
            }
        }
        memset(vis,0,sizeof vis);
    }
    inline void bfs(int s,int *dis,int *X)
    {
        p.push(st[s]);
        X[st[s]]=s;
        while(!p.empty())
        {
            int tp=p.front();
            p.pop();
            for(nod i=head[tp];i;i=i->nxt)
            {
                if(dis[i->to]==dis[tp]+i->dis&&!X[i->to]&&!vis[i->to])
                {
                    p.push(i->to);
                    X[i->to]=s;
                }
            }
        }
    }
    inline void build(tre now,int l,int r)
    {
        now->l=l;
        now->r=r;
        now->dat=0x7fffffff;
        if(l==r) return;
        int mid=(l+r)>>1;
        now->ls=new tree();
        now->rs=new tree();
        build(now->ls,l,mid);
        build(now->rs,mid+1,r);
    }
    inline void update(tre now,int x,int y,int k)
    {
        if(now->l>y||now->r<x) return;
        if(x<=now->l&&now->r<=y)
        {
            now->dat=min(now->dat,k);
            return;
        }
        update(now->ls,x,y,k);
        update(now->rs,x,y,k);
    }
    inline void query(tre now)
    {
        if(now->l==now->r)
        {
            ans[now->l]=now->dat;
            return;
        }
        now->ls->dat=min(now->ls->dat,now->dat);
        now->rs->dat=min(now->rs->dat,now->dat);
        query(now->ls);
        query(now->rs);
    }
    signed main()
    {
        n=read();
        m=read();
        for(int a,b,c,i=1;i<=m;i++)  //m写成n,死了一个多小时
        {
            a=read();
            b=read();
            c=read();
            add(a,b,c);
            add(b,a,c);
        }
        memset(diss,0x7f,sizeof diss);
        memset(dist,0x7f,sizeof dist);
        dij(1,diss);
        dij(n,dist);   //两遍dij
        for(int i=1;i!=n;)   //标记边
        {
            vis[i]=true;
            st[++cnt]=i;
            for(nod now=head[i];now;now=now->nxt)
            {
                if(dist[i]==dist[now->to]+now->dis)
                {
                    now->vis=true;
                    i=now->to;
                    break;
                }
            }
        }
        st[++cnt]=n;   //最短路的点
        vis[n]=true;
        for(int i=1;i<cnt;i++)
            bfs(i,diss,L);
        for(int i=cnt;i>=1;i--)    //两次bfs(图的联通)
            bfs(i,dist,R); 
        tre root=new tree();   //我TM就是写指针你咬我。。。。 
        build(root,1,cnt);    //建树
        for(int i=1;i<=n;i++)
            for(nod now=head[i];now!=NULL;now=now->nxt)   
            {
                if(now->vis) continue;
                if(L[i]<R[now->to]&&L[i]&&R[now->to])
                {
                    update(root,L[i],R[now->to]-1,diss[i]+dist[now->to]+now->dis);   //更新线段树
                }
            }
        query(root);//  求ans
        int num=0;
        int maxn=0;
        for(int i=1;i<cnt;i++)
        {
            if(ans[i]>maxn)  //累计
            {
                maxn=ans[i];
                num=1;
            }
            else if(ans[i]==maxn)
                num++;
        }
        if(maxn==diss[n]) num+=m-cnt+1;  //刚好是最短路;
        put(maxn);
        putchar(' ');
        put(num);
        return 0;
    }
  • 相关阅读:
    leetcode108 Convert Sorted Array to Binary Search Tree
    leetcode98 Validate Binary Search Tree
    leetcode103 Binary Tree Zigzag Level Order Traversal
    leetcode116 Populating Next Right Pointers in Each Node
    Python全栈之路Day15
    Python全栈之路Day11
    集群监控
    Python全栈之路Day10
    自动部署反向代理、web、nfs
    5.Scss的插值
  • 原文地址:https://www.cnblogs.com/olinr/p/9629550.html
Copyright © 2020-2023  润新知