• HDU 2242 双连通分量 考研路茫茫——空调教室


    思路就是求边双连通分量,然后缩点,再用树形DP搞一下。

    代码和求强连通很类似,有点神奇,=_=,慢慢消化吧

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <vector>
      5 #include <stack>
      6 using namespace std;
      7 
      8 const int maxn = 10000 + 10;
      9 const int maxm = 20000 + 10;
     10 
     11 int n, m;
     12 int a[maxn];
     13 
     14 struct Edge
     15 {
     16     int v, nxt;
     17 }edges[maxm * 2];
     18 int ecnt;
     19 int head[maxn];
     20 
     21 bool vis[maxn];
     22 
     23 void AddEdge(int u, int v)
     24 {
     25     edges[ecnt].v = v;
     26     edges[ecnt].nxt = head[u];
     27     head[u] = ecnt++;
     28 }
     29 
     30 stack<int> S;
     31 int dfs_clock, scc_cnt;
     32 int low[maxn], pre[maxn], sccno[maxn], w[maxn];
     33 
     34 void dfs(int u, int fa)
     35 {
     36     low[u] = pre[u] = ++dfs_clock;
     37     S.push(u);
     38 
     39     for(int i = head[u]; ~i; i = edges[i].nxt)
     40     {
     41         if(i == (fa ^ 1)) continue;
     42         int v = edges[i].v;
     43         if(!pre[v])
     44         {
     45             dfs(v, i);
     46             low[u] = min(low[u], low[v]);
     47         }
     48         else if(!sccno[v]) low[u] = min(low[u], pre[v]);
     49     }
     50 
     51     if(pre[u] == low[u])
     52     {
     53         scc_cnt++;
     54         for(;;)
     55         {
     56             int x = S.top(); S.pop();
     57             sccno[x] = scc_cnt;
     58             w[scc_cnt] += a[x];
     59             if(x == u) break;
     60         }
     61     }
     62 }
     63 
     64 void find_scc()
     65 {
     66     scc_cnt = dfs_clock = 0;
     67     memset(w, 0, sizeof(w));
     68     memset(pre, 0, sizeof(pre));
     69     memset(sccno, 0, sizeof(sccno));
     70     for(int i = 0; i < n; i++) if(!pre[i]) dfs(i, -1);
     71 }
     72 
     73 vector<int> G[maxn];
     74 
     75 void dfs2(int u)
     76 {
     77     vis[u] = true;
     78     for(int i = 0; i < G[u].size(); i++)
     79     {
     80         int v = G[u][i];
     81         if(vis[v]) continue;
     82         dfs2(v);
     83         w[u] += w[v];
     84     }
     85 }
     86 
     87 int main()
     88 {
     89     while(scanf("%d%d", &n, &m) == 2 && n)
     90     {
     91         int sum = 0;
     92         for(int i = 0; i < n; i++) { scanf("%d", a + i); sum += a[i]; }
     93 
     94         memset(head, -1, sizeof(head));
     95         ecnt = 0;
     96 
     97         while(m--)
     98         {
     99             int u, v; scanf("%d%d", &u, &v);
    100             AddEdge(u, v); AddEdge(v, u);
    101         }
    102 
    103         find_scc();
    104 
    105         if(scc_cnt == 1) { puts("impossible"); continue; }
    106 
    107         for(int i = 1; i <= scc_cnt; i++) G[i].clear();
    108         for(int u = 0; u < n; u++)
    109             for(int i = head[u]; ~i; i = edges[i].nxt)
    110             {
    111                 int v = edges[i].v;
    112                 if(sccno[u] != sccno[v]) G[sccno[u]].push_back(sccno[v]);
    113             }
    114 
    115         memset(vis, false, sizeof(vis));
    116         dfs2(1);
    117 
    118         int ans = 1000000000;
    119         for(int i = 1; i <= scc_cnt; i++) ans = min(ans, abs(sum - w[i] * 2));
    120         printf("%d
    ", ans);
    121     }
    122 
    123     return 0;
    124 }
    代码君
  • 相关阅读:
    只需 4 步,手把手教你如何实现滤镜功能
    paip.提升用户体验---c++ qt自定义窗体(1)---标题栏的绘制
    socket网络编程的一些基础知识
    图像处理、模式识别、模式分类、机器视觉推荐图书
    数据挖掘、机器学习和模式识别关系与区别
    Qt4_VS10 程序打包发布
    Qt之多线程
    QT中.pro文件的写法
    高斯定理的证明
    《Linear Algebra and Its Applications》-chaper3-行列式-行列式初等变换
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4721540.html
Copyright © 2020-2023  润新知