Codeforces Round #375 (Div. 2) F. st-Spanning Tree
阿新 • • 發佈:2018-11-15
傳送門:Codeforces Round #375 (Div. 2) F. st-Spanning Tree
題意:
給你n個點,m條邊,有兩個給定的點S,T以及它們在生成樹中最大的度數
求能否構造出一棵樹,使得這兩個點的度數滿足要求
思路:
求出不使用與S,T有關的邊構成的聯通塊
這些聯通塊與S,T有三種聯通情況
1.只與S相連
2.只與T相連
3.與S和T均相連
記錄一下已經使用的邊的數量就可以了
#include<bits/stdc++.h> using namespace std; const int N=5e5+10; struct Edge{ int from,to; }e[N]; vector<Edge>tmp,ans,mp[N]; int f[N],flag[N]; int find(int x){ return f[x]==x ? x:f[x]=find(f[x]); } int main(){ int n,m,s,t,ds,dt,degree_s=0,degree_t=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) scanf("%d%d",&e[i].from,&e[i].to); scanf("%d%d%d%d",&s,&t,&ds,&dt); //構造出與S,T無關的若干個聯通塊 for(int i=1;i<=m;i++){ if(e[i].from==s||e[i].to==s||e[i].from==t||e[i].to==t) tmp.push_back(e[i]); else{ int x=find(e[i].from),y=find(e[i].to); if(x!=y) f[x]=y,ans.push_back(e[i]); } } bool Sta=false;//標記是否有S-T這條邊 for(int i=0;i<tmp.size();i++){ if(tmp[i].to==s||tmp[i].to==s||tmp[i].to==t||tmp[i].to==t) swap(tmp[i].from,tmp[i].to); int x=find(tmp[i].from),y=find(tmp[i].to); if(x+y==s+t) Sta=true; else if(x==s) flag[y]|=1,mp[y].push_back(tmp[i]); else if(y==s) flag[x]|=1,mp[x].push_back(tmp[i]); else if(x==t) flag[y]|=2,mp[y].push_back(tmp[i]); else if(y==t) flag[x]|=2,mp[x].push_back(tmp[i]); } for(int i=1;i<=n;i++){ if(flag[i]==1){ //只與S相連 degree_s++; ans.push_back(mp[i][0]); } else if(flag[i]==2){//只與T相連 degree_t++; ans.push_back(mp[i][0]); } } bool Flag=false; for(int i=1;i<=n;i++) if(flag[i]==3){ if(Flag==false){ int cnt=0; for(int j=0;j<mp[i].size();j++){ if(mp[i][j].from==s&&(cnt&1)==0) ans.push_back(mp[i][j]),cnt|=1; else if(mp[i][j].from==t&&(cnt&2)==0) ans.push_back(mp[i][j]),cnt|=2; } degree_s++,degree_t++; Flag=true; } else{ int st=ds-degree_s < dt-degree_t ? t:s; for(int j=0;j<mp[i].size();j++) if(mp[i][j].from==st){ ans.push_back(mp[i][j]); break; } st==t ? ++degree_t:++degree_s; } } if(Flag==false&&Sta){ degree_s++,degree_t++; ans.push_back((Edge){s,t}); } if(degree_s<=ds&°ree_t<=dt&&ans.size()==n-1){ printf("Yes\n"); for(int i=0;i<ans.size();i++) printf("%d %d\n",ans[i].from,ans[i].to); } else printf("No\n"); return 0; } --------------------- 作者:_zidaoziyan 來源:CSDN 原文:https://blog.csdn.net/acm_fighting/article/details/52735228?utm_source=copy