小清新贪心+分类讨论,因为边的数组开小了WA了好久……
首先我们贪心地选出不包含\(s,t\)的边,用这些边尽量地将除了\(s,t\)外的\(n-2\)个点连通
接下来考虑每个连通块,由于题目保证图初始连通,因此只有三种情况,即要么其中仅有和\(s\)相连的边;仅有和\(t\)相连的边;或者同时有向\(s,t\)连接的边
考虑前两种情况这个连通块的选择就唯一确定了,因此可以直接处理
最后后面那种情况我们优先找一个连通块同时向\(s,t\)连边(因为最后图必须连通),然后剩下的连通块就卡着上界随便连即可
注意一个corner case就是不存在同时有向\(s,t\)连接的边时,说明图中一定有直接连接\(s,t\)的边,这时要把这条边连上
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef __int128 i128;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=400005;
int n,m,s,t,ds,dt,tx[N],ty[N],fa[N],c[N][2]; set <pi> edges; vector <pi> ans;
inline int getfa(CI x)
{
return fa[x]!=x?fa[x]=getfa(fa[x]):x;
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) fa[i]=i;
for (i=1;i<=m;++i) scanf("%d%d",&tx[i],&ty[i]); scanf("%d%d%d%d",&s,&t,&ds,&dt);
bool est=0; for (i=1;i<=m;++i)
{
int x=tx[i],y=ty[i];
if ((x==s&&y==t)||(x==t&&y==s)) { est=1; continue; }
if (x!=s&&x!=t&&y!=s&&y!=t)
{
if (getfa(x)!=getfa(y)) ans.push_back(pi(x,y));
fa[getfa(x)]=getfa(y); continue;
}
edges.insert(pi(x,y)); edges.insert(pi(y,x));
}
for (i=1;i<=n;++i) if (i!=s&&i!=t)
{
if (edges.count(pi(i,s))) c[getfa(i)][0]=i;
if (edges.count(pi(i,t))) c[getfa(i)][1]=i;
}
int Ds=0,Dt=0; for (i=1;i<=n;++i) if (i!=s&&i!=t&&getfa(i)==i)
{
if (c[i][0]==0&&c[i][1]==0) assert(0);
if (c[i][0]==0) ++Dt,ans.push_back(pi(t,c[i][1]));
if (c[i][1]==0) ++Ds,ans.push_back(pi(s,c[i][0]));
}
bool flag=0; for (i=1;i<=n;++i) if (i!=s&&i!=t&&getfa(i)==i&&c[i][0]&&c[i][1])
{
if (!flag) { ++Ds,++Dt,ans.push_back(pi(s,c[i][0])),ans.push_back(pi(t,c[i][1])),flag=1; continue; }
if (Ds<ds) ++Ds,ans.push_back(pi(s,c[i][0])); else ++Dt,ans.push_back(pi(t,c[i][1]));
}
if (!flag&&est) ++Ds,++Dt,ans.push_back(pi(s,t));
if (Ds<=ds&&Dt<=dt)
{
assert(ans.size()==n-1); puts("Yes");
for (auto [x,y]:ans) printf("%d %d\n",x,y);
} else puts("No");
return 0;
}
标签:typedef,int,Tree,连通,long,CF723F,Spanning,include,define
From: https://www.cnblogs.com/cjjsb/p/17775564.html