• 洛谷 2296 寻找道路


    【题解】

      先建反向图,dfs求出哪些点可以到达终点。

      再建正向图,dfs求出哪些点可以作为路径上的点。

      最后在合法的点之间连边,跑dijkstra.

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define LL long long
     5 #define rg register
     6 #define N 10010
     7 #define M 200010
     8 using namespace std;
     9 int n,m,tot,st,ed,fa,son,last[N],dis[N],pos[N];
    10 bool arr[N],ok[N],vis[N];
    11 struct edge{int to,pre;}e[M];
    12 struct heap{int p,d;}h[N];
    13 struct rec{int u,v;}r[M];
    14 inline int read(){
    15     int k=0,f=1; char c=getchar();
    16     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    17     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    18     return k*f;
    19 }
    20 void dfs(int x){
    21     arr[x]=1;
    22     for(rg int i=last[x],to;i;i=e[i].pre)if(!arr[to=e[i].to]) dfs(to);
    23 }
    24 void dfs2(int x){
    25     vis[x]=1; bool can=1;
    26     for(rg int i=last[x],to;i;i=e[i].pre){
    27         if(!arr[to=e[i].to]) can=0;
    28         if(!vis[to]) dfs2(to);
    29     }
    30     ok[x]=can&arr[x];
    31 }
    32 inline void up(int x){
    33     while((fa=x>>1)&&h[fa].d>h[x].d) swap(h[x],h[fa]),swap(pos[h[x].p],pos[h[fa].p]),x=fa;
    34 }
    35 inline void down(int x){
    36     while((son=x<<1)<=tot){
    37         if(h[son+1].d<h[son].d&&son<tot) son++;
    38         if(h[son].d<h[x].d) swap(h[son],h[x]),swap(pos[h[son].p],pos[h[x].p]),x=son;
    39         else return;
    40     }
    41 }
    42 void dijkstra(int x){
    43     for(rg int i=1;i<=n;i++) dis[i]=1e9;
    44     h[tot=pos[x]=1]=(heap){x,dis[x]=0};
    45     while(tot){
    46         int now=h[1].p; pos[h[tot].p]=1; h[1]=h[tot--]; if(tot) down(1);
    47         for(rg int i=last[now],to;i;i=e[i].pre)if(dis[to=e[i].to]>dis[now]+1){
    48             dis[to]=dis[now]+1;
    49             if(!pos[to]) h[pos[to]=++tot]=(heap){to,dis[to]};
    50             else h[pos[to]].d=dis[to];
    51             up(pos[to]);
    52         }
    53     }
    54 }
    55 int main(){
    56     n=read(); m=read();
    57     for(rg int i=1,u,v;i<=m;i++){
    58          u=r[i].u=read(),v=r[i].v=read();
    59          e[++tot]=(edge){u,last[v]}; last[v]=tot;
    60     }
    61     st=read(); ed=read();
    62     dfs(ed);
    63 //    for(rg int i=1;i<=n;i++) printf("%d ",arr[i]); puts("arr");
    64     
    65     memset(last,0,sizeof(last)); tot=0;
    66     for(rg int i=1;i<=m;i++){
    67         int u=r[i].u,v=r[i].v;
    68         e[++tot]=(edge){v,last[u]}; last[u]=tot;
    69     }
    70     dfs2(st); ok[ed]=1;
    71 //    for(rg int i=1;i<=n;i++) printf("%d ",ok[i]); puts("ok");
    72     if(!ok[st]){puts("-1"); return 0;}
    73     
    74     memset(last,0,sizeof(last)); tot=0;
    75     for(rg int i=1,u,v;i<=m;i++)if(ok[u=r[i].u]&&ok[v=r[i].v])
    76         e[++tot]=(edge){v,last[u]},last[u]=tot;
    77     dijkstra(st);
    78     if(dis[ed]!=1e9) printf("%d
    ",dis[ed]);
    79     else puts("-1");
    80     return 0; 
    81 }
  • 相关阅读:
    HDU 2643 Rank:第二类Stirling数
    HDU 4372 Count the Buildings:第一类Stirling数
    HDU 3625 Examining the Rooms:第一类Stirling数
    HDU 3682 To Be an Dream Architect:查重【三维坐标系中点在实数上的映射】
    POJ 3311 Hie with the Pie:TSP(旅行商)【节点可多次经过】
    bzoj 1050 旅行comf
    luogu 3958 奶酪
    luogu 3952 时间复杂度
    luogu 3951 小凯的疑惑
    bzoj 1016 最小生成树计数
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9886090.html
Copyright © 2020-2023  润新知