CodeForces 723F st-Spanning Tree

$dfs$,构造。

类似于$k$度限制生成树的想法,可以将$s$和$t$先从图中删去,将剩下的部分求连通块,每个连通块内部很容易构造生成树,每个连通块缩成一个点来处理。

连通块分三种:

$1$.只与$s$有边

$2$.只与$t$有边

$3$.与$s$和$t$都有边

前两种没办法,只能和$s$和$t$相连。如果没有第三种,那么$s$和$t$之前需要连一条边。如果有第三种,在第三种里面选出一个来和$s$、$t$连,其余的当做第一种和第二种处理。

连边的过程中判断$s$和$t$的度是否满足条件即可。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<ctime>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-10;
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar();
    x = 0;
    while(!isdigit(c)) c = getchar();
    while(isdigit(c))
    {
        x = x * 10 + c - ‘0‘;
        c = getchar();
    }
}

struct Edge
{
    int a,b,nx;
}e[800010];
int h[200010];
int n,m,sz,s,t,ds,dt;
int belong[200010],block;
vector<int>ansx,ansy;

struct X
{
    int e1,e2;
}w[200010];

set<int>SS,TT;

void add(int a,int b)
{
    e[sz].a=a; e[sz].b=b; e[sz].nx=h[a]; h[a]=sz++;
}

void dfs(int x)
{
    belong[x]=block;
    for(int i=h[x];i!=-1;i=e[i].nx)
    {
        int to=e[i].b;
        if(belong[to]!=0) continue;
        if(to==s) continue;
        if(to==t) continue;

        ansx.push_back(x);
        ansy.push_back(to);

        dfs(to);
    }
}

int main()
{
    cin>>n>>m; memset(h,-1,sizeof h);
    for(int i=1;i<=m;i++)
    {
        int a,b; cin>>a>>b;
        add(a,b); add(b,a);
    }
    cin>>s>>t>>ds>>dt;

    for(int i=1;i<=n;i++)
    {
        if(i==s) continue;
        if(i==t) continue;
        if(belong[i]!=0) continue;
        block++; dfs(i);
    }

    for(int i=1;i<=block;i++) w[i].e1=w[i].e2=-1;

    for(int i=0;i<sz;i=i+2)
    {
        if(e[i].a==s&&(e[i].b!=s&&e[i].b!=t))
        {
            SS.insert(belong[e[i].b]);
            if(w[belong[e[i].b]].e1==-1) w[belong[e[i].b]].e1=i;
        }
        if(e[i].b==s&&(e[i].a!=s&&e[i].a!=t))
        {
            SS.insert(belong[e[i].a]);
            if(w[belong[e[i].a]].e1==-1) w[belong[e[i].a]].e1=i;
        }
        if(e[i].a==t&&(e[i].b!=s&&e[i].b!=t))
        {
            TT.insert(belong[e[i].b]);
            if(w[belong[e[i].b]].e2==-1) w[belong[e[i].b]].e2=i;
        }
        if(e[i].b==t&&(e[i].a!=s&&e[i].a!=t))
        {
            TT.insert(belong[e[i].a]);
            if(w[belong[e[i].a]].e2==-1) w[belong[e[i].a]].e2=i;
        }
    }

    int sum=0; vector<int>tmp;
    for(int i=1;i<=block;i++)
    {
        if(SS.count(i)&&TT.count(i)) { tmp.push_back(i); continue; }
        if(SS.count(i))
        {
            ansx.push_back(e[w[i].e1].a);
            ansy.push_back(e[w[i].e1].b);
            ds--;
        }
        else
        {
            ansx.push_back(e[w[i].e2].a);
            ansy.push_back(e[w[i].e2].b);
            dt--;
        }
    }

    if(tmp.size()==0)
    {
        ansx.push_back(s);
        ansy.push_back(t);
        ds--; dt--;
    }

    else
    {
        ansx.push_back(e[w[tmp[0]].e1].a);
        ansy.push_back(e[w[tmp[0]].e1].b);
        ansx.push_back(e[w[tmp[0]].e2].a);
        ansy.push_back(e[w[tmp[0]].e2].b);

        ds--; dt--;

        for(int i=1;i<tmp.size();i++)
        {
            if(ds>0)
            {
                ansx.push_back(e[w[tmp[i]].e1].a);
                ansy.push_back(e[w[tmp[i]].e1].b);
                ds--;
            }
            else if(dt>0)
            {
                ansx.push_back(e[w[tmp[i]].e2].a);
                ansy.push_back(e[w[tmp[i]].e2].b);
                dt--;
            }
        }

    }

    if(ds<0||dt<0||ansx.size()!=n-1) printf("No\n");
    else
    {
        printf("Yes\n");
        for(int i=0;i<ansx.size();i++)
            printf("%d %d\n",ansx[i],ansy[i]);
    }

    return 0;
}
时间: 2024-10-05 04:11:10

CodeForces 723F st-Spanning Tree的相关文章

Codeforces 618D Hamiltonian Spanning Tree(树的最小路径覆盖)

题意:给出一张完全图,所有的边的边权都是 y,现在给出图的一个生成树,将生成树上的边的边权改为 x,求一条距离最短的哈密顿路径. 先考虑x>=y的情况,那么应该尽量不走生成树上的边,如果生成树上有一个点的度数是n-1,那么必然需要走一条生成树上的边,此时答案为x+y*(n-2). 否则可以不走生成树上的边,则答案为y*(n-1). 再考虑x<y的情况,那么应该尽量走生成树上的边,由于树上没有环,于是我们每一次需要走树的一条路,然后需要从非生成树上的边跳到树的另一个点上去, 显然跳的越少越好,于

codeforces 723F : st-Spanning Tree

Description There are n cities and m two-way roads in Berland, each road connects two cities. It is known that there is no more than one road connecting each pair of cities, and there is no road which connects the city with itself. It is possible tha

CodeForces 618D Hamiltonian Spanning Tree

题意:要把所有的节点都访问一次,并且不能重复访问,有两种方式访问,一种是根据树上的路径 走和当前节点连接的下一个节点cost x, 或者可以不走树上边,直接跳到不与当前节点连接的节点,cost y 分析: 别被树吓着! 一定会走n-1条路,那么就是有一些走树上的边,有一些不走. 如果树上的路径cost更大(x >= y),那么尽可能的不走树上的路径,那么根据尝试可以找到规律 如果有一个节点是所有节点的父节点,也就是说这个节点的度为n-1,那么只会走一个x其他都是y 如果没有这个节点,一定可以全部

Codeforces 1218D Xor Spanning Tree FWT

根据题目描述可知是个特殊的仙人掌, 然后把环扣出来fwt算方案数就好了. #include<bits/stdc++.h> #define fi first #define se second #define mk make_pair #define PII pair<int, int> using namespace std; const int N = 1 << 17; const int mod = (int)1e9 + 7; const int mod2 = 99

CF609E. Minimum spanning tree for each edge

题解:随便构造一颗最小生成树 然后对于其他不在树上的边  考虑到 删除这条链上的最大值在把这条边加上去 能得到这条边所在的最小生成树 可以LCT维护 但是明显这个题是静态的树就没必要LCT 当然我觉得最优的是树剖以后ST nlogn的的复杂度 也可以树剖+线段树nlog^2的复杂度 #include <bits/stdc++.h> const int MAXN=2e5+10; #define ll long long using namespace std; ll read(){ ll x=0

HDU 4896 Minimal Spanning Tree(矩阵快速幂)

题意: 给你一幅这样子生成的图,求最小生成树的边权和. 思路:对于i >= 6的点连回去的5条边,打表知907^53 mod 2333333 = 1,所以x的循环节长度为54,所以9个点为一个循环,接下来的9个点连回去的边都是一样的.预处理出5个点的所有连通状态,总共只有52种,然后对于新增加一个点和前面点的连边状态可以处理出所有状态的转移.然后转移矩阵可以处理出来了,快速幂一下就可以了,对于普通的矩阵乘法是sigma( a(i, k) * b(k, j) ) (1<=k<=N), 现在

【HDU 4408】Minimum Spanning Tree(最小生成树计数)

Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Kruskal algorithm of minimum spanning tree, XXX finds that there might be multiple solutions. Given an undirected weighted graph with n (1<=n<=100) vertex

BNUOJ 26229 Red/Blue Spanning Tree

Red/Blue Spanning Tree Time Limit: 2000ms Memory Limit: 131072KB This problem will be judged on HDU. Original ID: 426364-bit integer IO format: %I64d      Java class name: Main Given an undirected, unweighted, connected graph, where each edge is colo

HDOJ 题目4408 Minimum Spanning Tree(Kruskal+Matrix_Tree)

Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1408    Accepted Submission(s): 450 Problem Description XXX is very interested in algorithm. After learning the Prim algori

Codeforces 461B Appleman and Tree(木dp)

题目链接:Codeforces 461B Appleman and Tree 题目大意:一棵树,以0节点为根节点,给定每一个节点的父亲节点,以及每一个点的颜色(0表示白色,1表示黑色),切断这棵树的k条边,使得树变成k+1个联通分量.保证每一个联通分量有且仅有1个黑色节点.问有多少种切割方法. 解题思路:树形dp,dp[i][0]和dp[i][1]分别表示子树一下的切割方法中,i节点所在联通块不存在黑节点和已经存在一个黑节点的方案数. #include <cstdio> #include &l