Minimum Cut
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 .
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 .
1 4 5 1 2 2 3 3 4 1 3 1 4
Case #1: 2
题意:给你一个无向图G(无自环和重边),问你至少要去掉几条边才能使G不连通,需要满足的条件是去掉的边需包含一条所给的图G的生成树的边
换句话说即删除最少的边使得G图变得不连通,删除的其中一条边属于生成树T
为了方便理解,拿样例做个说明
上图中红色部分为图G的生成树
如果一条边e(u,v)不属于生成树T,那么对于u和 v来说它连接到其他子树的贡献是1,
所以要num[u]++, num[v]++; (num存的是删除某个点需要删除的边的数量)!
如果e(u,v)这条边不是LCA(u,v)的这个点所要删除的边。那么两个端点的贡献就是2!所以要num[tt]-=2;
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 80010;
const int maxm = 26;
int dp[2*maxn][maxm]; //数组开到2*N,因为遍历后序列长度为2*n-1
bool vis[maxn];
struct edge
{
int from, to;
int next;
} e[2*maxn];
int tot,head[maxn];
int cnt;
int num[maxn];
void init()
{
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
memset(num,0,sizeof(num));
cnt = 0;
}
void addedge(int u, int v)
{
e[cnt].from = u;
e[cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt++;
}
int ver[2*maxn], R[2*maxn], first[maxn];
//ver:节点编号 R:深度 first:点编号位置
void dfs(int u ,int dep)
{
vis[u] = true;
ver[++tot] = u;
first[u] = tot;
R[tot] = dep;
for(int k=head[u]; k!=-1; k=e[k].next)
if( !vis[e[k].to] )
{
int v = e[k].to;
dfs(v, dep+1);
ver[++tot] = u;
R[tot] = dep;
}
}
void ST(int n)
{
for(int i=1; i<=n; i++)
dp[i][0] = i;
for(int j=1; (1<<j)<=n; j++)
{
for(int i=1; i+(1<<j)-1<=n; i++)
{
int a = dp[i][j-1] , b = dp[i+(1<<(j-1))][j-1];
dp[i][j] = R[a]<R[b]?a:b;
}
}
}
//中间部分是交叉的。
int RMQ(int l,int r)
{
int k=0;
while((1<<(k+1))<=r-l+1)
k++;
int a = dp[l][k], b = dp[r-(1<<k)+1][k]; //保存的是编号
return R[a]<R[b]?a:b;
}
int LCA(int u ,int v)
{
int x = first[u] , y = first[v];
if(x > y) swap(x,y);
int res = RMQ(x,y);
return ver[res];
}
int DFS(int u,int fa)
{
for(int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].to;
if(v == fa)
continue;
DFS(v, u);
num[u]+=num[v];
}
return 0;
}
int main()
{
int t;
int cas = 0;
int n, m;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&n,&m);
int u, v;
for(int i = 0; i < n-1; i++)
{
scanf("%d%d",&u,&v);
addedge(u, v);
addedge(v, u);
}
for(int i = n; i <= m; i++)
{
scanf("%d%d",&u,&v);
int tt = LCA(u, v);
num[u]++;
num[v]++;
num[tt]-=2;//一条边两个端点 贡献为2
}
DFS(1, 1);
int ans = INF;
for(int i = 2; i <= n; i++)
{
ans = min(ans, num[i]+1);
}
printf("Case #%d: %d\n",++cas,ans);
}
return 0;
}
菜鸟成长记
不好意思,谢谢各位帮我纠正了此题错误的做法,是我考虑得不够全面,而且被水数据蒙骗了一把,万分感谢大家!此外,身为菜鸟的我实在是有心无力,目前还无法自己A掉此题,故转载了大神的解法,未经其同意擅自转载表示抱歉,@WDNLWZD,以下水过的解法会留着引以为戒,愿与大家共勉
题意:给你一个无向图G(无自环和重边),问你至少要去掉几条边才能使G不连通,需要满足的条件是去掉的边需包含一条所给的图G的生成树的边
换句话说即删除最少的边使得G图变得不连通,删除的其中一条边属于生成树T
为了方便理解,拿样例做个说明
上图中红色部分为图G的生成树
假设我们暂时先不考虑生成树,那么要使图G不连通,我们只需删去与度数最小的结点相连的边即可使图G不连通
而多考虑一个生成树的话,如果仍删去与度数最小的结点相连的边,有可能会删去生成树的两条边(如图中删去与结点2相连的边),因此,我们只需删去与[(仅与1条生成树边相连的且度数最小的)结点相连的]边即可
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<deque>
#include<functional>
#include<iterator>
#include<set>
#include<utility>
#include<stack>
#include<queue>
using namespace std;
#define maxn 22222
#define inf 1500000007
int deg1[maxn],deg2[maxn];
int main()
{
int i,j,k,n,x,y,m,T,p=1;
scanf("%d",&T);
while(T--)
{
memset(deg1,0,sizeof(deg1));
memset(deg2,0,sizeof(deg2));
scanf("%d%d",&n,&m);
for(i=1;i<=n-1;++i)
{
scanf("%d%d",&x,&y);
deg1[x]++;
deg1[y]++;
}
for(;i<=m;++i)
{
scanf("%d%d",&x,&y);
deg2[x]++;
deg2[y]++;
}
m=5555555;
for(i=1;i<=n;++i)
{
if(deg1[i] == 1)
m = min(m,deg2[i]);
}
printf("Case #%d: %d\n",p++,m+1);
}
return 0;
}
菜鸟成长记