zoukankan      html  css  js  c++  java
  • Aizu

    题意:给出一张有向图,每条边有长度,对于每条边,你要回答将该边的方向取反后,从起点到终点的最短距离是增加or减小or不变。

    首先求出起点到所有点的最短距离和所有点到终点的最短距离(两次DIjkstra,第二次跑反向边即可),并建出最短路图。设ds[u]为起点到点u的最短距离,dt[u]为点u到终点的最短距离,对于每条边,设该边的两个端点u->v,以及边权c,分情况讨论:

    若ds[v]+c+dt[u]>dt[s],此时将边取反后最短距离减小,否则需要判断该边是否为最短路图上s到t的割边,若是则最短距离增加,否则不变。

    如何判断该边是否为s到t的割边?其实方法很简单,如果是割边,那么从s到t的所有路径都经过该边。由于最短路图是个DAG,设in[u]表示从起点走到u的路径数,out[v]表示从v走到终点的路径数,则每条边被通过的路径数=in[u]*out[v],只需判断in[u]*out[v]是否等于out[s]即可。注意这个路径数可能会很大甚至存不下,但由于只需要判断是否相等用哈希就可以,可以用unsigned long long溢出自动取模。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef unsigned long long ll;
     4 const int N=1e5+10,inf=0x3f3f3f3f;
     5 int n,m,hd[N],ne;
     6 ll in[N],out[N],ds[N],dt[N],vis[N];
     7 struct E {int u,v,c,nxt;} e[N<<1];
     8 void addedge(int u,int v,int c) {e[ne]= {u,v,c,hd[u]},hd[u]=ne++;}
     9 struct D {
    10     int u;
    11     ll g;
    12     bool operator<(const D& b)const {return g>b.g;}
    13 };
    14 priority_queue<D> q;
    15 void upd(int u,ll ad,ll* dp) {
    16     if(dp[u]>ad)dp[u]=ad,q.push({u,ad});
    17 }
    18 void dij() {
    19     memset(ds,inf,sizeof ds);
    20     while(q.size())q.pop();
    21     upd(1,0,ds);
    22     while(q.size()) {
    23         int u=q.top().u;
    24         ll g=q.top().g;
    25         q.pop();
    26         if(ds[u]!=g)continue;
    27         for(int i=hd[u]; ~i; i=e[i].nxt)if(!(i&1))upd(e[i].v,g+e[i].c,ds);
    28     }
    29     memset(dt,inf,sizeof dt);
    30     while(q.size())q.pop();
    31     upd(2,0,dt);
    32     while(q.size()) {
    33         int u=q.top().u;
    34         ll g=q.top().g;
    35         q.pop();
    36         if(dt[u]!=g)continue;
    37         for(int i=hd[u]; ~i; i=e[i].nxt)if(i&1)upd(e[i].v,g+e[i].c,dt);
    38     }
    39 }
    40 ll dfsin(int u) {
    41     ll& ret=in[u];
    42     if(vis[u])return ret;
    43     vis[u]=1,ret=0;
    44     if(u==1)return ret=1;
    45     for(int i=hd[u]; ~i; i=e[i].nxt)if(i&1) {
    46             int v=e[i].v;
    47             if(dt[u]+e[i].c!=dt[v])continue;
    48             ret+=dfsin(v);
    49         }
    50     return ret;
    51 }
    52 ll dfsout(int u) {
    53     ll& ret=out[u];
    54     if(vis[u])return ret;
    55     vis[u]=1,ret=0;
    56     if(u==2)return ret=1;
    57     for(int i=hd[u]; ~i; i=e[i].nxt)if(!(i&1)) {
    58             int v=e[i].v;
    59             if(ds[u]+e[i].c!=ds[v])continue;
    60             ret+=dfsout(v);
    61         }
    62     return ret;
    63 }
    64 int main() {
    65     memset(hd,-1,sizeof hd),ne=0;
    66     scanf("%d%d",&n,&m);
    67     while(m--) {
    68         int u,v,c;
    69         scanf("%d%d%d",&u,&v,&c);
    70         addedge(u,v,c);
    71         addedge(v,u,c);
    72     }
    73     dij();
    74     memset(vis,0,sizeof vis);
    75     for(int i=1; i<=n; ++i)dfsin(i);
    76     memset(vis,0,sizeof vis);
    77     for(int i=1; i<=n; ++i)dfsout(i);
    78     for(int i=0; i<ne; i+=2) {
    79         int u=e[i].u,v=e[i].v;
    80         if(dt[1]>ds[v]+e[i].c+dt[u])puts("HAPPY");
    81         else if(ds[u]+e[i].c==ds[v]&&in[u]*out[v]==out[1])puts("SAD");
    82         else puts("SOSO");
    83     }
    84     return 0;
    85 }
  • 相关阅读:
    latex插入图片
    装virtualenv和flask
    GitHub Pages写博客
    用模拟退火算法进行特征选择
    用遗传算法进行特征选择
    智能垃圾桶
    蚁群算法 与 A*算法 寻找最优路径 对比 (pygame)
    pygame
    pyinstaller打包python应用程序
    内网渗透之信息收集-linux
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11694386.html
Copyright © 2011-2022 走看看