码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5452——Minimum Cut——————【树链剖分+差分前缀和】

时间:2015-09-24 19:07:50      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:

Minimum Cut

Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 895    Accepted Submission(s): 387


Problem Description
Given a simple unweighted graph G (an undirected graph containing no loops nor multiple edges) with n nodes and m edges. Let T be a spanning tree of G.
We say that a cut in G respects T if it cuts just one edges of T.

Since love needs good faith and hypocrisy return for only grief, you should find the minimum cut of graph G respecting the given spanning tree T.
 

 

Input
The input contains several test cases.
The first line of the input is a single integer t (1t5) which is the number of test cases.
Then t test cases follow.

Each test case contains several lines.
The first line contains two integers n (2n20000) and m (n1m200000).
The following n1 lines describe the spanning tree T and each of them contains two integers u and v corresponding to an edge.
Next mn+1 lines describe the undirected graph G and each of them contains two integers u and v corresponding to an edge which is not in the spanning tree T.
 

 

Output
For each test case, you should output the minimum cut of graph G respecting the given spanning tree T.
 

 

Sample Input
1
4 5
1 2
2 3
3 4
1 3
1 4
 

 

Sample Output
Case #1: 2
 

 

Source
 
 
题目大意:给你一棵树,然后给加上m-n+1条边。问你必须切掉树上的一条边,使得图不连通最少需要切多少条边。
 
解题思路:树链剖分。用树链剖分将树上的边都编上编号。每次加边的时候就在u--v之间加权值1。最后找到边权最小的即为答案。这里用差分前缀和来处理区间。
 
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
struct Edge{
    int v,w,next;
}edges[maxn*5];
int head[maxn];
int fa[maxn],dep[maxn],siz[maxn],son[maxn];
int top[maxn],w[maxn];
int c[maxn];
int tot,totw;
const int INF=0x3f3f3f3f;
void init(){
    tot=0;
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
}
void addedge(int _u,int _v){
    edges[tot].v=_v;
    edges[tot].next=head[_u];
    head[_u]=tot++;
    edges[tot].v=_u;
    edges[tot].next=head[_v];
    head[_v]=tot++;
}
void dfs1(int u,int _fa,int _dep ){ //得到dep数组、fa数组、siz数组、son数组
    dep[u] = _dep;
    fa[u] = _fa;
    siz[u] = 1;
    for(int i=head[u]; i!=-1; i=edges[i].next){
        Edge &e = edges[i];
        if(e.v != _fa){
            dfs1(e.v,u, _dep+1);
            siz[u]+=siz[ e.v ];
            if(son[u]==-1  || siz[son[u]] <siz[e.v]){
                son[u] = e.v;
            }
        }
    }
}
void dfs2(int u,int _top){  //得到top数组、w数组
    top[u]=_top;
    w[u]=totw++;
    if(son[u]!=-1){
        dfs2(son[u],_top);
        for(int i=head[u]; i != -1; i = edges[i].next){
            Edge &e = edges[i];
            if(e.v != fa[u]&&e.v!=son[u]){
                dfs2(e.v,e.v);
            }
        }
    }
}
void update(int u,int v,int val){   //修改u---v路径上的权值
    int f1=top[u],f2=top[v];    //找到u,v所在重链的链头
    while(f1!=f2){  //处理不在同一条重链上的情况
        if(dep[f1]<dep[f2]){
            swap(f1,f2);
            swap(u,v);
        }
        c[w[f1]] +=val; //这里用的是差分前缀和的方法实现
        c[w[u]+1]-=val;
        u=fa[f1];
        f1=top[u];
    }
    if(dep[u]>dep[v]){   //让u处于靠近根的位置
        swap(u,v);
    }
    c[w[son[u]]]+=val;  //处理在同一条重链上的情况
    c[w[v]+1]-=val;
}
int main(){
    int t,n,m,cnt=0;
    scanf("%d",&t);
    while(t--){
        init();
        scanf("%d%d",&n,&m);
        int a,b;
        for(int i=1;i<=n-1;i++){
            scanf("%d%d",&a,&b);
            addedge(a,b);
        }
        dfs1(1,-1,1);
        totw=1;
        dfs2(1,1);
        memset(c,0,sizeof(c));
        for(int i=1;i<=m-n+1;i++){
            scanf("%d%d",&a,&b);
            update(a,b,1);
        }
        for(int i=1;i<=n;i++){
            c[i]+=c[i-1];
        }
        int ans=INF;
        for(int i=1;i<=n;i++){
            if(c[i]!=0&&c[i]){
                ans=min(ans,c[i]);
            }
        }
        printf("Case #%d: %d\n",++cnt,ans+1);
    }
    return 0;
}

  

HDU 5452——Minimum Cut——————【树链剖分+差分前缀和】

标签:

原文地址:http://www.cnblogs.com/chengsheng/p/4836016.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!