Codeforces Round #375 (Div. 2)F. st-Spanning Tree

题目链接:F. st-Spanning Tree

题解:先把与s,t无关的边遍历一次,把能够链接两个不同的并查集连起来,然后在把每个块标记一下看能否与s,t相连,如果有一个块s和t都可以连就先把s,t联通,然后把只能与s和只能t相连的块分别与s,t相连

连的过程中维护ds,dt,最后在贪心把两个都可以连的连上去.最后看连的边数是否有n-1条,有的话就yes输出答案

  1 By lhclqslove, contest: Codeforces Round #375 (Div. 2), problem: (F) st-Spanning Tree, Accepted, #
  2  #include<bits/stdc++.h>
  3 #include<set>
  4 #include<cstdio>
  5 #include<iomanip>
  6 #include<iostream>
  7 #include<string>
  8 #include<cstring>
  9 #include<algorithm>
 10 #define pb push_back
 11 #define ll long long
 12 #define fi first
 13 #define se second
 14 #define PI 3.14159265
 15 #define ls l,m,rt<<1
 16 #define rs m+1,r,rt<<1|1
 17 #define eps 1e-7
 18 #define pii pair<int,int>
 19 typedef unsigned long long ull;
 20 const int mod=1e3+5;
 21 const ll inf=0x3f3f3f3f3f3f3f;
 22 const int maxn=2e5+5;
 23 using namespace std;
 24 int n,m,f[maxn],x[maxn*2],y[maxn*2],link1[maxn],link2[maxn];
 25 vector<pii>edge;
 26 set<int>yu;
 27 bool vis[maxn];
 28 vector<pii>ans;
 29 set<int>ss,tt;
 30 void init()
 31 {
 32     for(int i=0;i<maxn;i++)f[i]=i;
 33 }
 34 int find(int x)
 35 {
 36     if(f[x]==x)return x;
 37     else return f[x]=find(f[x]);
 38 }
 39 void link(int x,int y)
 40 {
 41     int fx=find(x);
 42     int fy=find(y);
 43     f[fy]=fx;
 44 }
 45 int main()
 46 {
 47     ios::sync_with_stdio(false);
 48     cin.tie(0);cout.tie(0);
 49     cin>>n>>m;
 50     init();
 51     for(int i=0;i<m;i++)
 52     {
 53         cin>>x[i]>>y[i];
 54     }
 55     int s,t,ds,dt;
 56     cin>>s>>t>>ds>>dt;
 57     if(m<n-1)
 58     {
 59         cout<<"No"<<endl;return 0;
 60     }
 61     for(int i=0;i<m;i++)
 62     {
 63         if(x[i]!=s&&x[i]!=t&&y[i]!=t&&y[i]!=s)
 64         {
 65             edge.pb({x[i],y[i]});
 66         }
 67         else
 68         {
 69             if(x[i]==s)ss.insert(y[i]);
 70             if(y[i]==s)ss.insert(x[i]);
 71             if(x[i]==t)tt.insert(y[i]);
 72             if(y[i]==t)tt.insert(x[i]);
 73         }
 74     }
 75     for(int i=0;i<edge.size();i++)
 76     {
 77         if(find(edge[i].fi)!=find(edge[i].se))
 78         {
 79             ans.pb(edge[i]);
 80             link(edge[i].se,edge[i].fi);
 81         }
 82     }
 83     for(int to:tt)
 84     {
 85         int fto=find(to);
 86         link1[fto]=1;
 87     }
 88      for(int to:ss)
 89     {
 90         int fto=find(to);
 91         link2[fto]=1;
 92     }bool flag=false;
 93     if(!flag)//st相连
 94     {
 95         for(int to:tt)
 96         {
 97             if(to==s)continue;
 98             int fto=find(to);
 99             if(link2[fto])
100             {//cout<<to<<"UUU"<<t<<endl;
101                 if(dt){ans.pb({t,to});dt--;link(to,t);vis[find(to)]=1;break;}
102             }
103         }
104         for(int to:ss)
105         {
106             if(to==t)continue;
107             if(vis[find(to)])
108             {
109                 //cout<<to<<"SSS"<<s<<endl;
110                 if(ds)ans.pb({s,to}),ds--,link(to,s);
111                 flag=true;
112                 break;
113             }
114         }
115     }
116    // cout<<ds<<" "<<dt<<endl;
117     for(int to:tt)//只与t相连
118     {
119         if(to==s)continue;
120         int fto=find(to);
121         if(!link2[fto]&&fto!=find(t))
122         {
123            // cout<<"####"<<endl;
124             if(dt)ans.pb({to,t}),dt--,link(to,t);
125             else
126             {
127                 cout<<"No"<<endl;return 0;
128             }
129         }
130     }
131     for(int to:ss)//只与s相连
132     {
133         if(to==t)continue;
134         int fto=find(to);
135         if(!link1[fto]&&fto!=find(s))
136         {
137           //  cout<<"$$$$"<<endl;
138             if(ds)ans.pb({to,s}),ds--,link(s,to);
139             else
140             {
141                 cout<<"No"<<endl;return 0;
142             }
143         }
144     }
145     for(int to:ss)//个都相连
146     {
147         if(to==t)continue;
148         int fto=find(to);
149         if(fto!=find(s))
150         {
151             if(ds)
152             {
153                 ans.pb({to,s});ds--,link(s,to);
154             }
155         }
156     }
157     for(int to:tt)
158     {
159         if(to==s)continue;
160         int fto=find(to);
161         if(fto!=find(t))
162         {
163             if(dt)
164             {
165                 ans.pb({to,t});dt--,link(to,t);
166             }
167         }
168     }
169     if(find(s)!=find(t))
170     {
171         if(ds&&dt&&ss.count(t))
172         {
173             ans.pb({s,t});ds--;dt--;
174         }
175         else
176         {
177             cout<<"No"<<endl;return 0;
178         }
179     }
180     if(ans.size()==n-1)
181     {
182         cout<<"Yes"<<endl;
183         for(pii tmp :ans)
184         {
185             cout<<tmp.fi<<" "<<tmp.se<<endl;
186         }
187     }
188     else
189     {
190         cout<<"No"<<endl;
191     }
192     return 0;
193 }

 

转载于:https://www.cnblogs.com/lhclqslove/p/9341310.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值