zoukankan      html  css  js  c++  java
  • [ZJOI2008]骑士

    嘟嘟嘟

    n个点n条边,说明图中存在一个简单环,更准确的说是每一个连通块中存在一个简单环(因为图可能不连通)。

    然后有人给这个玩意起了个名字:基环外向树。

    然而并没有什么用。

    思路很简单:断环为链,就变成了一棵树了。为了防止断开的两端(x, y)同时被选,从x和y分别树形dp一下,然后硬性规定根节点不能选即可。

    树形dp就不说啦,就是没有上司的舞会。

    需要注意的是,找环不仅要记录端点,还要记录断开的边E。然后E和E ^ 1就是断开的边。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     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 int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const int maxn = 1e6 + 5;
     21 inline ll read()
     22 {
     23     ll ans = 0;
     24     char ch = getchar(), last = ' ';
     25     while(!isdigit(ch)) {last = ch; ch = getchar();}
     26     while(isdigit(ch)) {ans = (ans << 1) + (ans << 3) + ch - '0'; ch = getchar();}
     27     if(last == '-') ans = -ans;
     28     return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32     if(x < 0) x = -x, putchar('-');
     33     if(x >= 10) write(x / 10);
     34     putchar(x % 10 + '0');
     35 }
     36 
     37 int n, a[maxn];
     38 
     39 struct Edge
     40 {
     41     int nxt, to;
     42 }e[maxn << 1];
     43 int head[maxn], ecnt = -1;
     44 void addEdge(int x, int y)
     45 {
     46     e[++ecnt] = (Edge){head[x], y};
     47     head[x] = ecnt;
     48 }
     49 
     50 int rt1, rt2, E;        //E, E ^ 1:the edge wich is cutted
     51 bool vis[maxn], cir[maxn];
     52 void Find(int now, int _e)
     53 {
     54     vis[now] = cir[now] = 1;
     55     for(int i = head[now], v; i != -1; i = e[i].nxt)
     56     {
     57         v = e[i].to;
     58         if(cir[v] && i != (_e ^ 1))
     59         {
     60             rt1 = now; rt2 = v; E = i;
     61         }
     62         if(!vis[v]) Find(v, i);
     63     }
     64     cir[now] = 0;
     65 }
     66 
     67 ll dp[maxn][2];
     68 void dfs(int now, int f)
     69 {
     70     dp[now][0] = dp[now][1] = 0;
     71     for(int i = head[now], v; i != -1; i = e[i].nxt)
     72     {
     73         v = e[i].to;
     74         if(v == f || i == E || i == (E ^ 1)) continue;
     75         dfs(v, now);
     76         dp[now][1] += dp[v][0];
     77         dp[now][0] += max(dp[v][1], dp[v][0]);
     78     }
     79     dp[now][1] += a[now];
     80 }
     81 
     82 int main()
     83 {
     84     Mem(head, -1);
     85     n = read();
     86     for(int i = 1; i <= n; ++i)
     87     {
     88         a[i] = read(); 
     89         int x = read(); addEdge(i, x); addEdge(x, i);
     90     }
     91     ll ans = 0;
     92     for(int i = 1; i <= n; ++i) if(!vis[i])
     93     {
     94         Find(i, -1);
     95         dfs(rt1, 0);
     96         ll Max = 0;
     97         if(dp[rt1][0] > Max) Max = dp[rt1][0];
     98         dfs(rt2, 0);
     99         if(dp[rt2][0] > Max) Max = dp[rt2][0];
    100         ans += Max;
    101     }
    102     write(ans), enter;
    103     return 0;
    104 }
    View Code
  • 相关阅读:
    poj3348 Cow
    poj3348 Cow
    日常。。。强行续
    日常。。。又又续
    日常。。。又又续
    日常。。。又续
    内存检索
    MyLayer MyScene
    冒泡排序
    Array数组的排序与二分查字法
  • 原文地址:https://www.cnblogs.com/mrclr/p/9905362.html
Copyright © 2011-2022 走看看