zoukankan      html  css  js  c++  java
  • HDU2242 考研路茫茫——空调教室 割边 缩点

    第一次试手,就知道求割边,结果各种TLE,还改了向量为邻接表。其实问题是没有想到缩点之后是一棵树,之后每条树边都是割边,一遍dfs.

    /*
    *State: HDU2242 281MS 1604K 2899 B
    *题目大意:
    *        给一个有重边的无向图,然后要求判断能否删除一条边使图分为
    *        两个部分。图中每个点都有权重,如果可以分成两个部分,求这
    *        两个部分差值的最小值。
    *解题思路:
    *        先用tarjan缩点,把强连通分量都缩成点,因为强连通分量是不能
    *        删除一条边使图分开的。缩点之后就是一棵树,之后在这棵树上进行
    *        记忆化搜索。dfs一遍O(n)即可搜出结果。
    *解题感想:
    *        原来TLE了两次,一开始以为是vector超时了,后来才发觉自己没有
    *        缩点,而是求割边之后暴力,肯定TLE,当当初始化vst就够呛了。
    *        之后看了别人的思路,原来缩点之后就是树,树就简单了,一遍O(n)
    *        的dfs就出结果。还有注意求割边的时候,要注意是否有重边,有重边
    *        就稍微用flag标志下id就行啦,灵活简单。最后还wa了一次,因为忘记
    *        存在一个图就是强连通图的情况(代码忘记)。
    */
    View Code
      1 //求二次优化
      2 //State: 281 MS    2520 KB    GNU C++
      3 //没有快
      4 #include <iostream>
      5 #include <vector>
      6 #include <cmath>
      7 #include <cstring>
      8 #include <cstdio>
      9 #include <vector>
     10 using namespace std;
     11 
     12 const int MAXN = 10005;
     13 const int MAXE = 20005;
     14 typedef struct _node
     15 {
     16     int v, next;
     17 }N;
     18 N edge[3 * MAXE];
     19 int weight[MAXN], dfn[MAXN], low[MAXN];
     20 int step, tol, Min, half, head[MAXN], cntEdge;
     21 int myS[MAXN], top, scc, id[MAXN], idw[MAXN], vst[MAXN];
     22 int dp[MAXN];
     23 //建树
     24 vector<int> vec[MAXN];
     25 
     26 void init()
     27 {
     28     scc = 1;
     29     Min = INT_MAX;
     30     step = tol = half = top = cntEdge = 0;
     31     for(int i = 0; i < MAXN; i++)
     32     {
     33         vst[i] = dp[i] = idw[i] = 0;
     34         vec[i].clear();
     35         id[i] = -1;
     36         head[i] = -1;
     37         dfn[i] = low[i] = -1;
     38     }
     39 }
     40 
     41 //题目好像没有提到重边
     42 void addEdge(int u, int v)
     43 {
     44     edge[cntEdge].v = v;
     45     edge[cntEdge].next = head[u];
     46     head[u] = cntEdge++;
     47 
     48     edge[cntEdge].v = u;
     49     edge[cntEdge].next = head[v];
     50     head[v] = cntEdge++;
     51 }
     52 
     53 void tarjan_scc(int n, int father)
     54 {
     55     dfn[n] = low[n] = ++step;
     56     myS[top++] = n;
     57     int flag = 0;
     58     for(int f = head[n]; f != -1; f = edge[f].next)
     59     {
     60         int son = edge[f].v;
     61         if(son == father && !flag)
     62         {
     63             flag = 1;
     64             continue;
     65         }
     66         if(dfn[son] == -1)
     67         {
     68             tarjan_scc(son, n);
     69             low[n] = min(low[n], low[son]);
     70         }
     71         else
     72             low[n] = min(low[n], dfn[son]);
     73     }
     74 
     75     if(low[n] == dfn[n])
     76     {
     77         int tmp, flag = 0;
     78         do    
     79         {
     80             tmp = myS[--top];
     81             id[tmp] = scc;
     82             idw[scc] += weight[tmp];
     83 
     84         }while(top != 0 && tmp != n);
     85         scc++;
     86     }
     87 }
     88 
     89 void bulid_tree(int n)
     90 {
     91     for(int i = 0; i < n; i++)
     92     {
     93         for(int f = head[i]; f != -1; f = edge[f].next)
     94         {
     95             int u = i, v = edge[f].v;
     96             if(id[u] == id[v])
     97                 continue;
     98             else
     99             {
    100                 vec[id[u]].push_back(id[v]);
    101                 vec[id[v]].push_back(id[u]);
    102             }
    103         }
    104     }
    105 }
    106 
    107 int dfs_tree(int n)
    108 {
    109     vst[n] = 1;
    110     int tmp = idw[n];
    111     for(unsigned i = 0; i < vec[n].size(); i++)
    112     {
    113         int son = vec[n][i];
    114         if(!vst[son])
    115             tmp += dfs_tree(son);
    116     }
    117     dp[n] = tmp;
    118     half = tol - dp[n];
    119     if(abs(half - dp[n]) < Min)
    120         Min = abs(half - dp[n]);
    121     return dp[n];
    122 }
    123 
    124 int main(void)
    125 {
    126 #ifndef ONLINE_JUDGE
    127     freopen("in.txt", "r", stdin);
    128 #endif
    129 
    130     int n, m;
    131     while(scanf("%d %d", &n, &m) == 2)
    132     {
    133         init();
    134         for(int i = 0; i < n; i++)
    135         {
    136             scanf("%d", &weight[i]);
    137             tol += weight[i];
    138         }
    139         int u, v;
    140         for(int i = 0; i < m; i++)
    141         {
    142             scanf("%d %d", &u, &v);
    143             addEdge(u, v);
    144         }
    145 
    146         tarjan_scc(0, 0);
    147 
    148         bulid_tree(n);
    149 
    150         dfs_tree(1);
    151 
    152         if(scc > 2)
    153             printf("%d\n", Min);
    154         else
    155             printf("impossible\n");
    156         //cout << "********" << endl;
    157     }
    158     return 0;
    159 }
  • 相关阅读:
    问题建模---大纲---待补充
    塞库报表封装问题分析--一篇不太成功的问题分析报告
    哲学的根本问题--以人为本
    什么是本体论
    知行合一是做人的最高境界
    什么是问题?--人类才是最大的问题--所有的问题都是在人类认识世界和改造世界中产生的
    还原论与what、how、why
    selinux 开启和关闭
    Macbook上打开多个终端的方法
    PHPStorm 快捷键大全(Win/Linux/Mac)
  • 原文地址:https://www.cnblogs.com/cchun/p/2641075.html
Copyright © 2011-2022 走看看