您的位置:首页 > 其它

hdoj 5452 Minimum Cut 【LCA 求解点被环覆盖的次数】

2015-09-22 17:03 399 查看

Minimum Cut

Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)

Total Submission(s): 658 Accepted Submission(s): 292



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




忘贴了。。。

题意:给出一个图G和它的一个生成树T。现在要求删除生成树上的一条边和若干条其他边,使得图不连通。求能删除的最小边数。

思路:LCA 修改、记录每个点被覆盖环的次数,最后找出最小的覆盖次数+1就可以了。

我的代码不能对边权修改,若修改边权会TLE。还是太渣了o(╯□╰)o

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 20000+10
#define MAXM 200000+10
#define INF 0x3f3f3f3f
using namespace std;
struct Edge
{
    int to, next;
};
Edge edge[MAXM<<1];
int head[MAXN], edgenum;
int depth[MAXN];
int pre[MAXN];//记录节点前驱
int num[MAXN];//记录节点被环覆盖的次数
int N, M;
void init()
{
    edgenum = 0;
    memset(head, -1, sizeof(head));
}
void addEdge(int u, int v)
{
    edge[edgenum].to = v;
    edge[edgenum].next = head[u];
    head[u] = edgenum++;
}
void getMap()
{
    init();
    scanf("%d%d", &N, &M);
    int a, b;
    for(int i = 1; i < N; i++)
    {
        num[i] = 0;
        scanf("%d%d", &a, &b);
        addEdge(a, b);
        addEdge(b, a);
    }
}
void DFS(int u, int fa, int d)
{
    depth[u] = d;//记录深度
    for(int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        if(v == fa) continue;
        pre[v] = u;
        DFS(v, u, d+1);
    }
}
void find_depth()
{
    memset(depth, 0, sizeof(depth));
    memset(pre, 0, sizeof(pre));
    DFS(1, -1, 0);
}
int k = 1;
void work(int e1, int e2)
{
    while(1)//到达LCA
    {
        if(depth[e1] > depth[e2])
        {
            num[e1]++;
            e1 = pre[e1];
        }
        else
        {
            num[e2]++;
            e2 = pre[e2];
        }
        if(e1 == e2)
        {
            num[e1]++;
            break;
        }
    }
}
void solve()
{
    find_depth();
    int a, b;
    for(int i = 0; i < M-N+1; i++)
    {
        scanf("%d%d", &a, &b);
        if(a == b)
        {
            num[a]++;
            continue;
        }
        work(a, b);//对树边处理
    }
    int ans = INF;
    for(int i = 1; i <= N; i++)//求最小次数 环覆盖
        ans = min(num[i]+1, ans);
    printf("Case #%d: %d\n", k++, ans);
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        getMap();
        solve();
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: