zoukankan      html  css  js  c++  java
  • codeforces567E. President and Roads

    题目大意:总统要回家,会经过一些街道,每条街道都是单向的并且拥有权值。现在,为了让总统更好的回家,要对每一条街道进行操作:1)如果该街道一定在最短路上,则输出“YES”。2)如果该街道修理过后,该边所在的最短路可以取代原先的最短路,则输出“CAN x”,x是修改该街道的花费,就是权值减小的值。3)如果该街道是一条不连通的街道,或者修改过后权值小于等于0,则输出“NO”。

    解题思路:正向取边,求一次最短路得到d1[], 然后反向取边,再求一次最短路得到d2[]。接着开始判断每一条边是否在最短路上。初始最短路为Min,当d1[u]+d2[v]+dis==Min时,先判断该边是否一定为最短路上的边,是的话输出“YES”,否则在判断该边的权值是否大于1,是的话输出“CAN 1”,否则输出“NO”。当d1[u]+d2[v]+dis>Min时,先判断两段路的差值加一是否会大于等于该边的差值,是的话,输出“NO”,否则输出“CAN 差值加一”,其余情况均输出“NO”。还有一个问题,如何判断边是否一定在最短路上。先把最短路取出,重新建一张无向图,然后用tarjan算法求出哪些边是桥。桥就是一定在最短路上的边。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define maxn 200005
    #define maxm 200005
    #define inf 4557430888798830399LL
    using namespace std;
    typedef long long int64;
    char ch;
    int n,m,s,t,a[maxm],b[maxm],idx,dfn[maxn],low[maxn];
    int64 c[maxm],min_road;
    int siz,pos[maxn];
    struct Heap{
        int64 val;
        int num;
        bool operator <(const Heap b)const{return val<b.val;}
        bool operator >(const Heap b)const{return b<*this;}
        bool operator <=(const Heap b)const{return !(*this>b);}
        bool operator >=(const Heap b)const{return !(*this<b);}
        bool operator ==(const Heap b)const{return (*this<=b)&&(*this>=b);}
        bool operator !=(const Heap b)const{return !(*this==b);}
    }heap[maxn],tmp;
    struct Map{
        int tot,now[maxn],son[maxm],pre[maxm],val[maxm];
        int64 dist[maxn];
        void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}    
    }map[3];
    bool ok,bo[maxn],road[maxm];
    void read(int &x){
        for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
        for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
        if (ok) x=-x;
    }
    void read(int64 &x){
        for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
        for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
        if (ok) x=-x;
    }
    void heap_swap(Heap &a,Heap &b){swap(pos[a.num],pos[b.num]),swap(a,b);}
    void up(int son){
        int fa=son>>1;
        while (fa){
            if (heap[fa]<=heap[son]) break;
            heap_swap(heap[fa],heap[son]);
            son=fa,fa>>=1;
        }
    }
    void down(){
        int fa=1,son=fa<<1;
        while (son<=siz){
            if (son+1<=siz&&heap[son+1]<heap[son]) son++;
            if (heap[fa]<=heap[son]) break;
            heap_swap(heap[fa],heap[son]);
            fa=son,son<<=1;
        }
    }
    void dijkstra(Map &map,int s){
        siz=n;
        memset(map.dist,63,sizeof(map.dist));
        memset(bo,0,sizeof(bo));
        for (int i=1;i<=n;i++) heap[i].val=inf;
        for (int i=1;i<=n;i++) heap[i].num=i;
        for (int i=1;i<=n;i++) pos[i]=i;
        heap[s].val=0,up(pos[s]);
        for (;;){
            if (heap[1].val==inf||!siz) break;
            int u=heap[1].num;
            bo[u]=true,map.dist[u]=heap[1].val;
            heap_swap(heap[1],heap[siz--]),down();
            for (int p=map.now[u],v=map.son[p];p;p=map.pre[p],v=map.son[p]){
                if (heap[pos[v]].val>map.dist[u]+map.val[p]&&!bo[v])
                    heap[pos[v]].val=map.dist[u]+map.val[p],up(pos[v]);
            }
        }
    }
    void dfs(Map &map,int u,int t){
        dfn[u]=low[u]=++idx;
        for (int p=map.now[u],v=map.son[p];p;p=map.pre[p],v=map.son[p])
            if (!dfn[v]){
                dfs(map,v,p^1),low[u]=min(low[u],low[v]);
                if (low[v]>dfn[u]) road[pos[p>>1]]=1;
            }
            else if (t!=p) low[u]=min(low[u],dfn[v]);
    }
    int main(){
        read(n),read(m),read(s),read(t);
        for (int i=1;i<=m;i++) read(a[i]),read(b[i]),read(c[i]),map[0].put(a[i],b[i],c[i]),map[1].put(b[i],a[i],c[i]);
        dijkstra(map[0],s),dijkstra(map[1],t),min_road=map[0].dist[t],map[2].tot=1;
        for (int i=1;i<=m;i++) if (map[0].dist[a[i]]+map[1].dist[b[i]]+c[i]==min_road)
            map[2].put(a[i],b[i],c[i]),map[2].put(b[i],a[i],c[i]),pos[map[2].tot>>1]=i;//,cout<<a[i]<<' '<<b[i]<<endl;
        dfs(map[2],s,-1);
        for (int i=1;i<=m;i++)
            if (map[0].dist[a[i]]+map[1].dist[b[i]]+c[i]==min_road){
                if (road[i]) puts("YES");
                else if (c[i]>1) puts("CAN 1");
                else puts("NO");
            }
            else if (map[0].dist[a[i]]+map[1].dist[b[i]]+c[i]>min_road){
                if (min_road>map[0].dist[a[i]]+map[1].dist[b[i]]+1) printf("CAN %I64d
    ",map[0].dist[a[i]]+map[1].dist[b[i]]+c[i]-min_road+1);
                else puts("NO");
            }
            else puts("NO");
        return 0;
    }
  • 相关阅读:
    Linux文件查询笔记
    C语言学习和回顾
    hive的数据压缩
    进程线程那些事儿
    hive的数据存储格式
    hive的内置函数
    Hive自定义函数
    spark编译
    Impala的安装和使用
    数据库的读写分离
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/4894808.html
Copyright © 2011-2022 走看看