Minimum Cut (hdu 5452 离线LCA)

来源:互联网 发布:三维迷宫屏保 知乎 编辑:程序博客网 时间:2024/05/16 09:57

Minimum Cut

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


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
14 51 22 33 41 31 4
 

Sample Output
Case #1: 2
 

Source
2015 ACM/ICPC Asia Regional Shenyang Online
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:  5467 5466 5465 5464 5463 
 


题意:n个点m条边,前n-1条边构成这个图的生成树,现在删除一些边使得图不联通,且要求删除的边中有且仅有一条生成树上的边,问最小要删除多少条边。

思路:若要删除生成树上节点u的子树,那么就要删除u的子树中所有和另外一个树相连的边,还有减去u子树内部相连的边就是要删除的边数了。内部相连的边用LCA处理。

代码:

#include <iostream>#include <functional>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <string>#include <map>#include <stack>#include <vector>#include <set>#include <queue>#pragma comment (linker,"/STACK:102400000,102400000")#define pi acos(-1.0)#define eps 1e-6#define lson rt<<1,l,mid#define rson rt<<1|1,mid+1,r#define FRE(i,a,b)  for(i = a; i <= b; i++)#define FREE(i,a,b) for(i = a; i >= b; i--)#define FRL(i,a,b)  for(i = a; i < b; i++)#define FRLL(i,a,b) for(i = a; i > b; i--)#define mem(t, v)   memset ((t) , v, sizeof(t))#define sf(n)       scanf("%d", &n)#define sff(a,b)    scanf("%d %d", &a, &b)#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)#define pf          printf#define DBG         pf("Hi\n")typedef long long ll;using namespace std;#define INF 0x3f3f3f3f#define mod 1000000009const int maxn = 20010;const int MAXN = 200005;const int MAXM = 200010;const int N = 1005;struct Edge{    int to,next;}edge[maxn*2];struct Query{    int q,next;}query[MAXN*2];int n,m;int head[maxn],hed[maxn],tot1,tot2;int father[maxn];int num[maxn];bool vis[maxn];void init(){    tot1=tot2=0;    memset(head,-1,sizeof(head));    memset(hed,-1,sizeof(hed));    memset(vis,false,sizeof(vis));    memset(num,0,sizeof(num));    for (int i=0;i<=n;i++)        father[i]=i;}void addedge(int u,int v){    edge[tot1].to=v;    edge[tot1].next=head[u];    head[u]=tot1++;}void addquery(int u,int v){    query[tot2].q=v;    query[tot2].next=hed[u];    hed[u]=tot2++;}int find_father(int x){    if (x!=father[x])        father[x]=find_father(father[x]);    return father[x];}void Union(int u,int v){    father[find_father(v)]=find_father(u);}void Tarjan(int u,int fa){    vis[u]=true;    for (int i=head[u];~i;i=edge[i].next)    {        int v=edge[i].to;        if (vis[v]) continue;        if (v==fa) continue;        Tarjan(v,u);        num[u]+=num[v];        Union(u,v);    }    for (int i=hed[u];~i;i=query[i].next)    {        int v=query[i].q;        if (v==fa) continue;        num[u]++;        if (!vis[v]) continue;        num[find_father(v)]-=2;    }}int main(){#ifndef ONLINE_JUDGE    freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin);#endif    int i,j,t,cas=0;    int u,v;    scanf("%d",&t);    while (t--)    {        scanf("%d%d",&n,&m);        init();        for (i=1;i<n;i++)        {            scanf("%d%d",&u,&v);            addedge(u,v);            addedge(v,u);        }        for (i=n;i<=m;i++)        {            scanf("%d%d",&u,&v);            addquery(u,v);            addquery(v,u);        }        Tarjan(1,-1);        int Min=INF;        for (i=2;i<=n;i++)            Min=min(Min,num[i]);        if (n==1) Min=-1;        printf("Case #%d: %d\n",++cas,Min+1);    }    return 0;}



0 0
原创粉丝点击