P3128 [USACO15DEC]最大流Max Flow

二次联通门 : P3128 [USACO15DEC]最大流Max Flow

 

 

 

 

/*
    luogu P3128 最大流Max Flow
    
    说着最大流。。。
    其实跟最大流半毛钱关系没有
    
    是个数据结构题
    
    树剖预处理
    线段树维护区间最大值
    线段树区间修改 
    最后查询以1为根节点的子树中的最大值即可。。
     
*/
#include <cstdio>

#define Max 50090

inline int max (int a, int b)
{
    return a > b ? a : b;
}

inline int min (int a, int b)
{
    return a < b ? a : b;
}

inline int swap (int &a, int &b)
{
    int now = a;
    a = b;
    b = now;
}

void read (int &now)
{
    now = 0;
    register char word = getchar ();
    while (word < '0' || word > '9')
        word = getchar ();
    while (word <= '9' && word >= '0')
    {
        now = now * 10 + word - '0';
        word = getchar ();
    }
}

class Segment_Tree_Type
{
    private :
        
        struct Segment_Tree
        {
            int l;
            int r;
            int Mid;
            int Maxn;
            int Ruri;
        }
        
        tree[Max << 4];
        
    public :
        
        void Build (int l, int r, int now)
        {
            tree[now].l = l;
            tree[now].r = r;
            if (l == r)
                return ;
            tree[now].Mid = (l + r) >> 1;
            Build (l, tree[now].Mid, now << 1);
            Build (tree[now].Mid + 1, r, now << 1 | 1);
        }
        
        void Change_section (int l, int r, int now)
        {
            if (tree[now].l == l && tree[now].r == r)
            {
                tree[now].Maxn++;
                tree[now].Ruri++;
                return ;
            }
            if (tree[now].Ruri)
            {
                tree[now << 1].Maxn += tree[now].Ruri;
                tree[now << 1].Ruri += tree[now].Ruri;
                tree[now << 1 | 1].Maxn += tree[now].Ruri;
                tree[now << 1 | 1].Ruri += tree[now].Ruri;
                tree[now].Ruri = 0;
            }
            if (r <= tree[now].Mid)
                Change_section (l, r, now << 1);
            else if (l > tree[now].Mid)
                Change_section (l, r, now << 1 | 1);
            else
            {
                Change_section (l, tree[now].Mid, now << 1);
                Change_section (tree[now].Mid + 1, r, now << 1 | 1);
            }
            tree[now].Maxn = max (tree[now << 1].Maxn, tree[now << 1 | 1].Maxn);
        }

        int Query_section_Maxn (int l, int r, int now)
        {
            if (tree[now].l == l && tree[now].r == r)
                return tree[now].Maxn;
            if (tree[now].Ruri)
            {
                tree[now << 1].Maxn += tree[now].Ruri;
                tree[now << 1].Ruri += tree[now].Ruri;
                tree[now << 1 | 1].Maxn += tree[now].Ruri;
                tree[now << 1 | 1].Ruri += tree[now].Ruri;
                tree[now].Ruri = 0;
            }
            tree[now].Maxn = max (tree[now << 1].Maxn, tree[now << 1 | 1].Maxn);
            if (r <= tree[now].Mid)
                return Query_section_Maxn (l, r, now << 1);
            else if (l > tree[now].Mid)
                return Query_section_Maxn (l, r, now << 1 | 1);
            else 
                return max (Query_section_Maxn (l, tree[now].Mid, now << 1), Query_section_Maxn (tree[now].Mid + 1, r, now << 1 | 1));    
        }    
};

struct Edge_Type
{
    
    int Edge_Count;
    
    int edge_list[Max];
    
    struct Edges
    {
        int to;
        int next;
    }
    
    edge[Max << 2];
    
    void Add_Edge (int from, int to)
    {
        Edge_Count++;
        edge[Edge_Count].to = to;
        edge[Edge_Count].next = edge_list[from];
        edge_list[from] = Edge_Count;
        Edge_Count++;
        edge[Edge_Count].to = from;
        edge[Edge_Count].next = edge_list[to];
        edge_list[to] = Edge_Count;
    }
};

Segment_Tree_Type Tree;

Edge_Type Graph;

class Tree_Chain_Get_Type
{
    private :
        
        struct Point_Type
        {
            int size;
            int deep;
            int father;
            int up_chain_point;
            int tree_number;
            int end;
        }
        
        point[Max];
        
    public :
        
        int Count;
        
        void Dfs_1 (int now, int father)
        {
            int pos = Count++;
            point[now].father = father;
            point[now].deep = point[father].deep + 1;
            for (int i = Graph.edge_list[now]; i; i = Graph.edge[i].next)
                if (Graph.edge[i].to != father)
                    Dfs_1 (Graph.edge[i].to, now);
            point[now].size = Count - pos;
        }
        
        void Dfs_2 (int now, int chain)
        {
            int pos = 0;
            point[now].up_chain_point = chain;
            point[now].tree_number = ++Count;
            for (int i = Graph.edge_list[now]; i; i = Graph.edge[i].next)
                if (!point[Graph.edge[i].to].tree_number && point[Graph.edge[i].to].size > point[pos].size)
                    pos = Graph.edge[i].to;
            if (!pos)
            {
                point[now].end = Count;
                return ;
            }
            Dfs_2 (pos, chain);
            for (int i = Graph.edge_list[now]; i; i = Graph.edge[i].next)
                if (Graph.edge[i].to != pos && !point[Graph.edge[i].to].tree_number)
                    Dfs_2 (Graph.edge[i].to, Graph.edge[i].to);
            point[now].end = Count;
        }
        
        void Change (int x, int y)
        {
            while (point[x].up_chain_point != point[y].up_chain_point)
            {
                if (point[point[x].up_chain_point].deep < point[point[y].up_chain_point].deep)
                    swap (x, y);
                Tree.Change_section (point[point[x].up_chain_point].tree_number, point[x].tree_number, 1);
                x = point[point[x].up_chain_point].father; 
            }
            Tree.Change_section (min (point[x].tree_number, point[y].tree_number), max (point[x].tree_number, point[y].tree_number), 1); 
        }
        
        int Get_Start ()
        {
            return point[1].tree_number;
        }
        
        int Get_End ()
        {
            return point[1].end;
        }
};

Tree_Chain_Get_Type Make;
 
int M, N;

int main (int argc, char *argv[])
{
    read (N);
    read (M);
    int x, y;
    for (int i = 1; i < N; i++)
    {
        read (x);
        read (y);
        Graph.Add_Edge (x, y); 
    }
    Make.Dfs_1 (1, 0);
    Make.Count = 0;
    Make.Dfs_2 (1, 1);
    Tree.Build (1, N, 1);  
    while (M--)
    {
        read (x);
        read (y);
        Make.Change (x, y); 
    }
    printf ("%d", Tree.Query_section_Maxn (Make.Get_Start (), Make.Get_End (), 1));
    return 0;
}

 

posted @ 2017-05-10 20:53  ZlycerQan  阅读(221)  评论(1编辑  收藏  举报