zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    券商
    养生之道
    房产买卖
    货币常识
    虚拟币
    其他开源项目
    Shiro
    文件上传插件
    JAVA常见问题
    如何写好PPT
  • 原文地址:https://www.cnblogs.com/olinr/p/9629550.html
Copyright © 2011-2022 走看看