• luogu P2783 有机化学之神偶尔会做作弊


    嘟嘟嘟

    一道很水的黑题~~

    边双缩点后用lca求树上两点间路径即可。

    但是比较坑的是这道题是忽略重边的,结果我还特意考虑了重边,然后WA了几发。

    还有两个点TLE了,原因是建新图的时候出现了重边。这个重边不是算法的问题,因为边双缩点后不可能有重边,而是写法上的问题:在建无向边的时候,习惯addEdge(x, y), addEdge(y, x),然而边双建边的时候两个点之间实际上连了4条边。所以写的时候只用建单向边,形成的图却是无向图。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cmath>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<queue>
     10 #include<stack>
     11 using namespace std;
     12 #define enter puts("")
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const db eps = 1e-8;
     19 const int INF = 0x3f3f3f3f;
     20 const int maxn = 1e4 + 5;
     21 const int maxe = 5e4 + 5;
     22 inline ll read()
     23 {
     24     ll ans = 0;
     25     char ch = getchar(), las = ' ';
     26     while(!isdigit(ch)) las = ch, ch = getchar();
     27     while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
     28     if(las == '-') ans = -ans;
     29     return ans;
     30 }
     31 inline void write(ll x)
     32 {
     33     if(x < 0) putchar('-'), x = -x;
     34     if(x >= 10) write(x / 10);
     35     putchar(x % 10 + '0');
     36 }
     37 
     38 int n, m;
     39 
     40 struct Edge
     41 {
     42     int nxt, to;
     43 }e[maxe << 1], e2[maxe << 1];
     44 int head[maxn], ecnt = -1;
     45 void addEdge(int x, int y)
     46 {
     47     e[++ecnt] = (Edge){head[x], y};
     48     head[x] = ecnt;
     49 }
     50 
     51 int dfn[maxn], low[maxn], cnt = 0;
     52 bool in[maxn];
     53 int st[maxn], top = 0;
     54 int col[maxn], ccol = 0;
     55 void tarjan(int now, int f)
     56 {
     57     dfn[now] = low[now] = ++cnt;
     58     st[++top] = now; in[now] = 1;
     59     for(int i = head[now]; i != -1; i = e[i].nxt)
     60     {
     61         if(!dfn[e[i].to])
     62         {
     63             tarjan(e[i].to, now);
     64             low[now] = min(low[now], low[e[i].to]);
     65         }
     66         else if(e[i].to != f) low[now] = min(low[now], dfn[e[i].to]);
     67     }
     68     if(dfn[now] == low[now])
     69     {
     70         int x; ++ccol;
     71         do
     72         {
     73             x = st[top--];
     74             col[x] = ccol;
     75             in[x] = 0;
     76         }while(x != now);
     77     }
     78 }
     79 
     80 int head2[maxn], ecnt2 = -1;
     81 void addEdge2(int x, int y)
     82 {
     83     e2[++ecnt2] = (Edge){head2[x], y};
     84     head2[x] = ecnt2;
     85 }
     86 void newGraph(int now)
     87 {
     88     int u = col[now];
     89     for(int i = head[now]; i != -1; i = e[i].nxt)
     90     {
     91         int v = col[e[i].to];
     92         if(u == v) continue;
     93         addEdge2(u, v); //addEdge2(v, u);
     94     }
     95 }
     96 
     97 const int N = 20;
     98 int fa[maxn][25], dep[maxn];
     99 void dfs(int now, int f)
    100 {
    101     for(int i = 1; i <= N; ++i)
    102         fa[now][i] = fa[fa[now][i - 1]][i - 1];
    103     for(int i = head2[now]; i != -1; i = e2[i].nxt)
    104     {
    105         if(e2[i].to == f) continue;
    106         fa[e2[i].to][0] = now;
    107         dep[e2[i].to] = dep[now] + 1;
    108         dfs(e2[i].to, now);
    109     }
    110 }
    111 int lca(int x, int y)
    112 {
    113     if(dep[x] < dep[y]) swap(x, y);
    114     for(int i = N; i >= 0; --i)
    115         if(dep[x] - (1 << i) >= dep[y]) x = fa[x][i];
    116     if(x == y) return x;
    117     for(int i = N; i >= 0; --i)
    118         if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
    119     return fa[x][0];
    120 }
    121 
    122 void print(int x)
    123 {
    124     if(!x) return;
    125     print(x >> 1);
    126     write(x & 1);
    127 }
    128 void solve(int x, int y)
    129 {
    130     int z = lca(x, y);
    131     print(dep[x] - dep[z] + dep[y] - dep[z] + 1);
    132     enter;
    133 }
    134 
    135 int main()
    136 {
    137     Mem(head, -1);
    138     n = read(); m = read();
    139     for(int i = 1; i <= m; ++i)
    140     {
    141         int x = read(), y = read();
    142         addEdge(x, y); addEdge(y, x);
    143     }
    144     for(int i = 1; i <= n; ++i) if(!dfn[i]) tarjan(i, 0);
    145     Mem(head2, -1);
    146     for(int i = 1; i <= n; ++i) newGraph(i);
    147     dfs(col[1], 0);
    148     int q = read();
    149     for(int i = 1; i <= q; ++i)
    150     {
    151         int x = read(), y = read();
    152         solve(col[x], col[y]);
    153     }
    154     return 0;
    155 }
    View Code
  • 相关阅读:
    POJ 3683 Priest John&#39;s Busiest Day (2-SAT+输出可行解)
    Codeforces #2B The least round way(DP)
    避免死锁的银行家算法C++程序实现
    源代码编译安装MySQL5.6.12具体过程
    Android 设计模式
    Java与设计模式-适配器模式
    Java和Flex整合报错(五)
    三层架构—再思考
    怎样让DBGrid在按住Shift点鼠标的同时能将连续范围的多行选中?
    找出你的短板
  • 原文地址:https://www.cnblogs.com/mrclr/p/9861508.html
Copyright © 2020-2023  润新知