• 【缩点+拓扑判链】POJ2762 Going from u to v or from v to u?


    Description

    In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn't know how to decide if a task is possible. To make her life easier, Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?
     

    Solution

    缩点,满足题意的充要条件是存在一条完整的链,这个可以用“是否存在唯一拓扑序”解决。

    Code

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int maxn=1e5+5;
     6 
     7 int pre[maxn],low[maxn],clock;
     8 int scc[maxn],s[maxn],c,cnt;
     9 int head[maxn],e[maxn],nxt[maxn],k;
    10 void adde(int u,int v){
    11     e[++k]=v;nxt[k]=head[u];head[u]=k;
    12 }
    13 int _head[maxn],_e[maxn],_nxt[maxn],_k;
    14 void _adde(int u,int v){
    15     _e[++_k]=v;_nxt[_k]=_head[u];_head[u]=_k;
    16 }
    17 int n,m;
    18 
    19 int r[maxn],vis[maxn];
    20 int topo(){
    21     for(int i=1;i<=cnt;i++){
    22         int tot=0,u;
    23         for(int i=1;i<=cnt;i++)//偷懒
    24             if(!r[i]&&!vis[i]) tot++,u=i;
    25         if(tot>1) return 0;
    26         vis[u]=1;
    27         for(int i=_head[u];i;i=_nxt[i])
    28             r[_e[i]]--;
    29     }
    30     return 1;
    31 }
    32 
    33 void dfs(int u){
    34     pre[u]=low[u]=++clock;
    35     s[++c]=u;
    36     for(int i=head[u];i;i=nxt[i]){
    37         int v=e[i];
    38         if(!pre[v]){
    39             dfs(v);
    40             low[u]=min(low[u],low[v]);
    41         }
    42         else if(!scc[v]){
    43             low[u]=min(low[u],pre[v]);
    44         }
    45     }
    46     if(low[u]==pre[u]){
    47         cnt++;
    48         while(c){
    49             scc[s[c]]=cnt;
    50             if(s[c--]==u) break;
    51         }
    52     }
    53 }
    54 
    55 void clear(){
    56     memset(head,0,sizeof(head));
    57     memset(_head,0,sizeof(_head));
    58     memset(pre,0,sizeof(pre));
    59     memset(low,0,sizeof(low));
    60     memset(vis,0,sizeof(vis));
    61     memset(r,0,sizeof(r));
    62     c=cnt=k=_k=0;
    63 }
    64 
    65 int main(){
    66     int T;
    67     scanf("%d",&T);
    68     while(T--){
    69         clear();
    70         scanf("%d%d",&n,&m);
    71         for(int i=1;i<=m;i++){
    72             int u,v;
    73             scanf("%d%d",&u,&v);
    74             adde(u,v);
    75         }
    76         for(int i=1;i<=n;i++)
    77             if(!pre[i]) dfs(i);
    78             
    79         for(int i=1;i<=n;i++)
    80             for(int j=head[i];j;j=nxt[j]){
    81                 int u=scc[i],v=scc[e[j]];
    82                 if(u==v) continue;
    83                 else _adde(u,v),r[v]++;
    84             }
    85         
    86         if(topo()) printf("Yes
    ");
    87         else printf("No
    ");
    88     }
    89     return 0;
    90 }
  • 相关阅读:
    editable : false与 readonly 的区别
    Ubuntu环境下使用Jupyter Notebook查找桌面.csv文档的方法
    实验01——java模拟银行ATM系统
    Wannafly挑战赛26 御坂网络
    Wannafly挑战赛29 御坂美琴(递归,模拟)
    牛客练习赛31 龙魂合一萨坎与晶石
    牛客练习赛31
    Codeforces Round #520 (Div. 2)A. A Prank
    (花里胡哨)New Game!(牛客国庆集训派对Day1)
    Educational Codeforces Round 54 (Rated for Div. 2)A. Minimizing the String(签到题)
  • 原文地址:https://www.cnblogs.com/xkui/p/4579131.html
Copyright © 2020-2023  润新知