CodeForces 723F【DFS瞎搞】

题意:

给你一幅图,你要用这些边构造一个树,
s和t两个节点的度数不能超过ds dt
而且图是保证没有环
思路:

树的性质是:无环(已经保证),无向(保证),连通(还要判断)

首先把S,T点从图里剥离出来,就是把S和T点搞成几个连通块

对于这些连通块有三种:只与S连的,只与T连的,还有一种是两个都连的,

然后就是要把S和T与那些连通块相连,保证连通。

由于对于S和T相连的点并不是连通块的老大,而且S和T连出去的点还可能同时在一个连通块里;

所以预处理一下S和T连接点的老大,塞到set里去去个重,连一个子节点或者就是他本身就好了;

中间还要判断S和T的连通性,最后再判断一下度数就好啦

PS:主要是要知道树的性质,还有就是要知道树的哪些边是一定要连的;

好菜啊!!!

#include <bits/stdc++.h>
using namespace std;

const int N=2e5+10;

vector<int>ma[N];
vector<int>ans[N],tt[N],ss[N];
set<int>s;
set<int>t;
int num[N];
int S,T;
int pre[N];

void dfs(int x,int k)
{
    pre[x]=k;
    for(int i=0;i<ma[x].size();i++)
    {
        //printf("%d
",ma[x][i]);
        if(ma[x][i]==S||ma[x][i]==T||pre[ma[x][i]])
            continue;
        ans[x].push_back(ma[x][i]);
        dfs(ma[x][i],k);
    }
}

int main()
{
    int n,m;
    int x,y;
    int ds,dt;
    int ps,pt;
    scanf("%d%d",&n,&m);
    while(m--)
    {
        scanf("%d%d",&x,&y);
        ma[x].push_back(y);
        ma[y].push_back(x);
    }
    scanf("%d%d%d%d",&S,&T,&ds,&dt);
    //首先剥离与s和t连通的东东;
    memset(pre,0,sizeof(pre));
    for(int i=1;i<=n;i++)
    {
        if(i==S||i==T||pre[i])
            continue;
        dfs(i,i);
    }
    //然后就是从s的一些连通块,或者从t出发的一些连通块
    int flag=0;
    ps=pt=0;
    memset(num,0,sizeof(num));
    //建下边,去个重;
    for(int i=0;i<ma[S].size();i++)
    {
        if(ma[S][i]==T)
        {
            flag++;
            continue;
        }
        s.insert(pre[ma[S][i]]);
        ss[pre[ma[S][i]]].push_back(ma[S][i]);
    }
    for(int i=0;i<ma[T].size();i++)
    {
        if(ma[T][i]==S)
            continue;
        t.insert(pre[ma[T][i]]);
        tt[pre[ma[T][i]]].push_back(ma[T][i]);
    }

    set<int>::iterator it;
    for(it=s.begin();it!=s.end();it++)
        num[*it]++;
    for(it=t.begin();it!=t.end();it++)
    {
        num[*it]++;
        if(num[*it]==1)
        {
            ans[T].push_back(tt[*it][0]);
            num[*it]=0;
            pt++;
        }
    }
    for(it=s.begin();it!=s.end();it++)
    {
        if(num[*it]==1)
        {
            ans[S].push_back(ss[*it][0]);
            num[*it]=0;
            ps++;
        }
    }
    int ff=0;
    for(it=s.begin();it!=s.end();it++)
    {
        if(num[*it]>1)
        {
            if(!ff)
            {
                ans[S].push_back(ss[*it][0]);
                ans[T].push_back(tt[*it][0]);
                ps++;
                pt++;
                ff=1;
                continue;
            }
            if(ps<ds)
            {
                ans[S].push_back(ss[*it][0]);
                ps++;
            }
            else//不行的话只能给T啊!!!;
            {
                ans[T].push_back(tt[*it][0]);
                pt++;
            }
        }
    }
    if(!ff)//如果不能搞在一起的话
    {
        if(flag)//判断是否本来就在一起
        {
            ans[S].push_back(T);
            ps++;
            pt++;
        }
        else
        {
            puts("NO");
            return 0;
        }
    }
    if(ps>ds||pt>dt)
        puts("No");
    else
    {
        puts("Yes");
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<ans[i].size();j++)
            {
                printf("%d %d
",i,ans[i][j]);
            }
        }
    }
    return 0;
}




原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934735.html