CF 375(div 2) F题

来源:互联网 发布:ture和true知乎 编辑:程序博客网 时间:2024/04/29 07:09

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 31 22 33 11 2 1 1
output
Yes3 21 3
input
7 87 41 35 45 73 22 46 11 26 4 1 4
output
Yes1 35 73 27 42 46 1

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

#include<bits/stdc++.h>#define maxm 450000#define maxn 200100using 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-tint 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