2018 Petrozavodsk Winter Camp, Yandex Cup CFGym 102155C Block, Stock and Two Smoking Galaxy Notes

13 篇文章 0 订阅
2 篇文章 0 订阅

Description

I decided to start a new fancy project related to cryptocurrency, deep learning, self-driving cars and maybe mobile voice assistance (will decide that later). I already have a team consisting of n promising software engineers and last thing that has to be done is choosing a techlead among them.

All engineers except the techlead should be divided into teams consisting of one or two engineers (recently I read first ten pages of the book "Agile Software Development: Programming in Pairs" and found the described technique very useful!). For each pair of engineers I know if they can interact with each other effectively.

The choice of techlead and distribution into teams is effective if any two-member team consists of two engineers that can interact effectively, and in any team there is at least one engineer who can interact effectively with the techlead.

I want you to find an appropriate company structure as fast as possible, so that our startup can make an IPO or ICO (not quite sure yet what that means, no time for that now), or determine that it is impossible and the world of success and glory is not for me (at least for today).

Input

The first line of input contains two integers n and m (2 ≤ n ≤ 1000, 0 ≤ m ≤ 10 000), the number of software engineers and the number of successfully interacting pairs.

Each of the next m lines contains two integers ui, vi (1 ≤ ui, vi ≤ n, ui ≠ vi), the indices of engineers forming an effectively interacting pair.

I guarantee that all unordered pairs of engineers are different.

Output

Print a single word "No" if it is impossible to create a company structure satisfying my requirements.

Otherwise, print a word "Yes" in the first line.

In the second line print two integers l, k (1 ≤ l ≤ n, ), the index of the techlead and the number of teams.

Each of the next k lines should contain two integers t1 and t2 defining a team. If the team consists of two members, t1 and t2 should be indices of the engineers forming it, otherwise t1 should be the index of the only engineer in the team and t2 should be  - 1.

If there are multiple correct answers, print any of them.

Sample Input

Input

5 4
1 2
2 3
3 4
4 5

Output

Yes
3 2
2 1
4 5

Input

4 4
1 2
2 3
3 4
4 1

Output

Yes
1 2
2 3
4 -1

Input

4 3
1 2
2 3
3 1

Output

No

题意:n个人,m对人能匹配,选出一个领导者,让能与领导者匹配的人同不能和领导者匹配的人匹配,问是否能让不能与领导者匹配的人都被匹配

思路:这题数据真水,n最大1000,我n3的算法居然过了,我本来还准备上网络流的,这题直接枚举领导者,然后让能与领导者匹配的人同不能与领导者匹配的人求最大匹配,看是不是等于不能与领导者匹配的人数就好了

#include <iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
#define maxn 5050
int vis[maxn],line[maxn],n,m,d[maxn],head[maxn],pp[maxn],cnt=0,flag[maxn];
struct Edge
{
    int to,next;
} edge[maxn*10];
void addedge(int u,int v)
{
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
int head1[maxn],cnt1=0;
Edge edge1[maxn*10];
void addedge1(int u,int v)
{
    edge1[cnt1].to=v;
    edge1[cnt1].next=head1[u];
    head1[u]=cnt1++;
}
int dfs(int u)
{
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        int v=edge[i].to;
        if(!vis[v])
        {
            vis[v]=1;
            if(line[v]==-1||dfs(line[v])==1)
            {
                pp[u]=v;
                line[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
int slove(int u)
{
    memset(pp,-1,sizeof(pp));
    memset(line,-1,sizeof(line));
    int ans=0;
    //printf(" u=%d\n",u);
    for(int i=head1[u]; i!=-1; i=edge1[i].next)
    {
        int v=edge1[i].to;
        //printf("  v=%d\n",v);
        memset(vis,0,sizeof(vis));
        if(dfs(v)==1)
        {

            ans++;
        }
    }
    return ans;
}
void init1()
{
    memset(d,0,sizeof(d));
    cnt1=0;
    memset(head1,-1,sizeof(head1));
}
int main()
{
    scanf("%d %d",&n,&m);
    init1();
    int max1=0;
    for(int i=1; i<=m; i++)
    {
        int u,v;
        scanf("%d %d",&u,&v);
        addedge1(u,v);
        addedge1(v,u);
        d[u]++;
        d[v]++;
        max1=max(max(d[u],d[v]),max1);
    }
    //printf("max1=%d\n",max1);
    int f=0;
    for(int i=1; i<=n; i++)
    {
        //printf("i=%d\n",i);
        memset(head,-1,sizeof(head));
        memset(flag,0,sizeof(flag));
        cnt=0;
        int sum=0;
        flag[i]=1;
        for(int j=head1[i]; j!=-1; j=edge1[j].next)
        {
            sum++;
            int v=edge1[j].to;
            flag[v]=1;
        }
        for(int j=head1[i]; j!=-1; j=edge1[j].next)
        {
            int v=edge1[j].to;
            for(int k=head1[v]; k!=-1; k=edge1[k].next)
            {
                int u=edge1[k].to;
                if(flag[u]!=1)
                {
                    //printf("v=%d u=%d\n",v,u);
                    addedge(v,u);
                }
            }
        }
        int ans=slove(i);
        //printf("ans=%d\n",ans);
        if(ans==n-sum-1)
        {
            f=1;
            printf("Yes\n");
            printf("%d %d\n",i,sum);
            for(int j=head1[i]; j!=-1; j=edge1[j].next)
            {
                int v=edge1[j].to;
                printf("%d %d\n",v,pp[v]);
            }
            break;
        }


    }
    if(f==0)
        printf("No\n");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值