CF 375(div 2) F题

yfz太强啦~

这题很考验耐心(考验个屁耐心... By yfzcsc)

先把不要求的点连起来

然后在连必须与s连的点 必须与t连的点

然后一大堆特判 非常那啥(哪有什么特判啊... By yfzcsc)

话说没人写博客太不靠谱了 都闷声发大财啊

jumpy

F. st-Spanning Tree
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given an undirected connected graph consisting of n vertices and m edges. There are no loops and no multiple edges in the graph.

You are also given two distinct vertices s and t, and two values ds and dt. Your task is to build any spanning tree of the given graph (note that the graph is not weighted), such that the degree of the vertex s doesn't exceed ds, and the degree of the vertex t doesn't exceed dt, or determine, that there is no such spanning tree.

The spanning tree of the graph G is a subgraph which is a tree and contains all vertices of the graph G. In other words, it is a connected graph which contains n - 1 edges and can be obtained by removing some of the edges from G.

The degree of a vertex is the number of edges incident to this vertex.

n个点m条边的无向联通图,给定s和t,求一棵生成树,使s,t的度数不超过ds,dt

我写了1个小时+ 最后还面向数据编程(统计一下边数是否为n-1)

Input

The first line of the input contains two integers n and m (2 ≤ n ≤ 200 0001 ≤ m ≤ min(400 000, n·(n - 1) / 2)) — the number of vertices and the number of edges in the graph.

The next m lines contain the descriptions of the graph's edges. Each of the lines contains two integers u and v (1 ≤ u, v ≤ nu ≠ v) — the ends of the corresponding edge. It is guaranteed that the graph contains no loops and no multiple edges and that it is connected.

The last line contains four integers stdsdt (1 ≤ s, t ≤ ns ≠ t1 ≤ ds, dt ≤ n - 1).

Output

If the answer doesn't exist print "No" (without quotes) in the only line of the output.

Otherwise, in the first line print "Yes" (without quotes). In the each of the next (n - 1) lines print two integers — the description of the edges of the spanning tree. Each of the edges of the spanning tree must be printed exactly once.

You can output edges in any order. You can output the ends of each edge in any order.

If there are several solutions, print any of them.

Examples
input
3 3
1 2
2 3
3 1
1 2 1 1
output
Yes
3 2
1 3
input
7 8
7 4
1 3
5 4
5 7
3 2
2 4
6 1
1 2
6 4 1 4
output
Yes
1 3
5 7
3 2
7 4
2 4
6 1

yfzcsc精简版代码如下:(yfz的代码虽然精简 但是有几个问题:1、通篇没有空格,太丑了;2、括号不换行,写函数还一行写完,太丑了)

#include<bits/stdc++.h>
#define maxm 450000
#define maxn 200100
using namespace std;
struct edge{
	int u,v;
}e[maxm];
int f[maxn],n,m,s,t,ds,dt;
bool use[maxm],a[maxn][2],g;
int find(int  x){return f[x]==x?x:f[x]=find(f[x]);}
void fuck(int p,int& d,int z){
	for(int flag=0;flag<2;++flag)
		for(int i=1,x,y;i<=m;++i)if(!use[i]){
			if(e[i].u==s&&e[i].v==t)continue;
			if(e[i].u==t&&e[i].v==s)continue;
			if(e[i].u==p)x=e[i].u,y=e[i].v;
			else if(e[i].v==p)x=e[i].v,y=e[i].u;
			else continue;
			if(a[y][z]&&!flag)continue;
			int fu=find(x),fv=find(y);
			if(fu==fv)continue;
			else if(d==0)break;
			else if(d>0){
				f[fu]=fv;
				use[i]=true;
				d--;
			}
		}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)
		scanf("%d%d",&e[i].u,&e[i].v);
	scanf("%d%d%d%d",&s,&t,&ds,&dt);
	for(int i=1;i<=m;++i){
		if(e[i].u==s)a[e[i].v][0]=true;
		if(e[i].v==s)a[e[i].u][0]=true;
		if(e[i].u==t)a[e[i].v][1]=true;
		if(e[i].v==t)a[e[i].u][1]=true;
	}
	for(int i=1;i<=n;++i)f[i]=i;
	for(int i=1;i<=m;++i)if(e[i].u!=s&&e[i].u!=t&&e[i].v!=s&&e[i].v!=t){
		int fu=find(e[i].u),fv=find(e[i].v);
		if(fu==fv)continue;
		else f[fu]=fv,use[i]=true;
	}
	if(ds>dt)fuck(s,ds,1),fuck(t,dt,0);
	else fuck(t,dt,0),fuck(s,ds,1);
	if(find(s)!=find(t)&&a[s][1])
		ds--,dt--,g=true,f[find(s)]=find(t);
	if(ds<0||dt<0){
		printf("No\n");
		return 0;
	}
	for(int i=1;i<=n;++i)if(find(1)!=find(i)){
		printf("No\n");
		return 0;
	}
	printf("Yes\n");
	if(g)printf("%d %d\n",s,t);
	for(int i=1;i<=m;++i)if(use[i])printf("%d %d\n",e[i].u,e[i].v);
}


Wxh菜鸟代码如下(但是WXH的代码风格非常的好哇~)

#include<bits/stdc++.h>

using namespace std;

const int maxn=200020;

int n,m,cnt;

int s,t,ds,dt,d1,d2,d3,d4,tp;//d1-only s d2-only t d3-s,t d4-s-t

int f[maxn<<1],head[maxn<<1],ss[maxn<<1],tt[maxn<<1],vis[maxn<<1],vis2[maxn<<1],from[maxn<<1],to[maxn<<1];

int findfa(int x)
{
	return f[x]==x?x:f[x]=findfa(f[x]);
}

void uni(int x,int y)
{
	int p=findfa(x);
	int q=findfa(y);
	f[p]=q;
}

struct edge
{
	int to,nxt;
}e[maxn<<2];

void addedge(int from,int to)
{
	e[++cnt].to=to;
	e[cnt].nxt=head[from];
	head[from]=cnt;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) f[i]=i;
	for(int i=1;i<=m;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v);
		addedge(v,u);
	}
	scanf("%d%d%d%d",&s,&t,&ds,&dt);
	for(int i=1;i<=m;i++)
	{
		if(i!=s&&i!=t)
		{
			for(int j=head[i];j;j=e[j].nxt)
			{
				int y=e[j].to;
				if(y!=s&&y!=t&&findfa(i)!=findfa(y))
				{
					uni(i,y);
					from[++tp]=i;
					to[tp]=y;
				}
			}
		}
	}
	for(int i=head[s];i;i=e[i].nxt)
	{
		int y=e[i].to;
		if(!vis[findfa(y)])
		{
			vis[findfa(y)]=y;
		}
	}
	for(int i=head[t];i;i=e[i].nxt)
	{
		int y=e[i].to;
		if(!vis2[findfa(y)])
		{
			vis2[findfa(y)]=y;
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(i==s||i==t)
		{
			if(vis[i]||vis2[i])
				d4++;
		}
		else
		{
			if(vis[i]&&(!vis2[i])&&findfa(vis[i])!=findfa(s))
				d1++,from[++tp]=vis[i],to[tp]=s,uni(vis[i],s),vis[i]=0;//cout<<vis[i]<<s;
			else if((!vis[i])&&vis2[i]&&findfa(vis2[i])!=findfa(t))
				d2++,from[++tp]=vis2[i],to[tp]=t,uni(vis2[i],t),vis2[i]=0;
			else if(vis[i]&&vis2[i])
				d3++;
		}
	}
	ds-=d1;
	dt-=d2;
	if(ds<0||dt<0)
	{
		printf("No");
		return 0;
	}
	if(d3>ds+dt)
	{
		printf("No");
		return 0;
	}
	for(int i=1;i<=n;i++)
	{
		if(i!=s&&i!=t)
		{
			if(vis[i]&&ds>0&&findfa(vis[i])!=findfa(s))
			{
				from[++tp]=vis[i];//cout<<vis[i]<<" "<<s<<endl;
				to[tp]=s;
				uni(s,vis[i]);
				ds--;
			}
			if(vis2[i]&&dt>0&&findfa(vis2[i])!=findfa(t))
			{
				from[++tp]=vis2[i];
				to[tp]=t;//cout<<vis2[i]<<" "<<t<<endl;
				uni(t,vis2[i]);
				dt--;
			}
		}
	}
	if(findfa(s)!=findfa(t))
	{
		if(ds&&dt)
		{
			from[++tp]=s;
			to[tp]=t;
		}
		else
		{
			printf("No");
			return 0;
		}
	}
	if(tp<n-1)
	{
		printf("No");
		return 0;
	}
	printf("Yes\n");
	for(int i=1;i<=tp;i++)
	{
		printf("%d %d\n",from[i],to[i]);
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值