hdu 5452 Minimum Cut

Minimum Cut

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


 

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

2015 ACM/ICPC Asia Regional Shenyang Online

题意就贼JB坑(英语太差),数据更坑,数据貌似特别水。。。

题意: 首先给你一个生成树,然后给你几条非树边,现在你要当且仅当删除树边一条,删除非树边若干条,使得剩下的图为一个不连通的。

思路: 删除树边是一定的,,那么这样我可以枚举删除每一条树边,然后看如果删除这条树边的话,那么我还要删除多少条非树边,那么我要删除的非树边其实就是这条非树边的两个顶点分别在树边的左右两边。  这样我就可以先预处理出来所有的非树边对树边的影响,这里一个技巧一点的实现方法就是对于非树边的两个点u,v 对于uv 的LCA 我 -=2 ,然后对于u v +=1 这样在dfs回溯的时候直接更新一下val就可以,我们要找的就是除了根结点的最小的val  (这里就是把每条边对应他的v点)

代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N =2e4+5;
const int M =400005;

struct eee
{
    int v;
    int next;
}edge[M];

struct node
{
    int u,v;
}E[M];

int rmq[N*2]; /// 就是欧拉序列对应的深度序列

struct ST
{
    int mm[N*2];
    int anc[2*N][20];
    void init(int n)
    {
        mm[0]=-1;
        for(int i=1;i<=n;i++){
            mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
            anc[i][0]=i;
        }
        for(int j=1;j<=mm[n];j++){
            for(int i=1;i+(1<<j)-1<=n;i++){
                anc[i][j]=rmq[anc[i][j-1]] < rmq[anc[i+(1<<(j-1))][j-1]]?anc[i][j-1]:anc[i+(1<<(j-1))][j-1];
            }
        }
    }

    int query(int a,int b)
    {
        if(a>b) swap(a,b);
        int k=mm[b-a+1];
        return rmq[anc[a][k]] <= rmq[anc[b-(1<<k)+1][k]]?anc[a][k]:anc[b-(1<<k)+1][k];
    }
};

int tot,head[N];
int val[N];
int dfns[N*2];
int pp[N];
int cnt;
int clo;
ST st;
int n,m;

void init()
{
    tot=0;
    clo=cnt=0;
    memset(head,-1,sizeof(head));
    memset(val,0,sizeof(val));
}

void add(int u,int v)
{
    edge[++tot].v=v; edge[tot].next=head[u]; head[u]=tot;
}

void dfs(int u,int fa,int deep)
{
    dfns[++cnt]=u; rmq[cnt]=deep; pp[u]=cnt;
    //L[u]=++clo;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==fa) continue;
        dfs(v,u,deep+1);
        dfns[++cnt]=u;
        rmq[cnt]=deep;
    }
    //R[u]=clo;
}

void LCA_init(int rt,int node_num)
{
    cnt=0;
    dfs(rt,rt,0);
    st.init(2*node_num-1);
}

int LCA(int u,int v)
{
    return dfns[st.query(pp[u],pp[v])];
}

void dfs1(int u,int fa)
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==fa) continue;
        dfs1(v,u);
        val[u]+=val[v];
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    int kk=0;
    while(T--)
    {
        scanf("%d %d",&n,&m);
        int i;
        init();
        for(i=1;i<n;i++){
            scanf("%d %d",&E[i].u,&E[i].v);
            add(E[i].u,E[i].v);
            add(E[i].v,E[i].u);
        }
        LCA_init(1,n);

        for(;i<=m;i++){
            scanf("%d %d",&E[i].u,&E[i].v);
            int lca=LCA(E[i].u,E[i].v);
            //cout<<"lca "<<lca<<endl;
            val[lca]-=2;
            val[E[i].u]++;
            val[E[i].v]++;
        }
        dfs1(1,-1);
        int Ans=99999999;
        for(int i=2;i<=n;i++){
            Ans=min(Ans,val[i]);
        }
        printf("Case #%d: %d\n",++kk,Ans+1);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值