1. 程式人生 > >HDU 5452 Minimun Cut (lca+dfs)

HDU 5452 Minimun Cut (lca+dfs)

Minimum Cut

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

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 (1≤t≤5) 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 (2≤n≤20000) and m (n−1≤m≤200000). The following n−1 lines describe the spanning tree T and each of them contains two integers u and v corresponding to an edge. Next m−n+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

 思路:題意是先給一棵樹,然後在加一些無向邊變成一個連通圖,在只允許刪除樹中一條邊的情況下刪除最少邊使圖不連通。

如果光是一棵樹的話只要刪任意一條邊就可以達到目標變成兩個子樹,所以各個點的ans都為1,後面每來一個邊,都會使此邊相連的兩個點的到LCA上的所有點的ans++,因為要刪這條新邊兩個子樹才不連通。

程式碼:

#include<bits/stdc++.h>
using namespace std;

const int maxn=200010;

struct nod{
    int to,next;
}e[maxn*2];

int deep[maxn];
int ans[maxn];
int fa[maxn];
int head[maxn];
int tot;

void add(int f,int t){
        e[tot].to=t;
        e[tot].next=head[f];
        head[f]=tot++;
}

void dfs(int u,int fath,int dp){
    deep[u]=dp;
    ans[u]=1;
    fa[u]=fath;
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].to;
        if(v!=fath){
            dfs(v,u,dp+1);
        }
    }
}

void lca(int x,int y){
    while(x!=y){
        if(deep[x]>=deep[y]){
            ans[x]++;
            x = fa[x];
        }
        else {
            ans[y]++;
            y=fa[y];
        }
    }
}

int main(){
        int  t,n,m,l;
        scanf("%d",&t);
        int cas=0;
        while(t--){
            tot=0;///init
            memset(head,-1,sizeof(head));
            scanf("%d%d",&n,&m);
            int u,v;
            for(int i=1;i<n;i++) {
                scanf("%d%d",&u,&v);
                add(u,v);
                add(v,u);
            }

            dfs(1,0,1);

            for(int i=n;i<=m;i++) {
                scanf("%d%d",&u,&v);
                lca(u,v);
            }

            int res=0x3f3f3f3f;
            for(int i=2;i<=n;i++) res=min(res,ans[i]);

            printf("Case #%d: %d\n",++cas,res);
        }
}