1. 程式人生 > >Gym 101879C(dfs+圖論

Gym 101879C(dfs+圖論

題意:有n個小島,已經有m條無向邊相連,有k條無向邊待選,問能否選擇一些邊使得能從一個點出發不重複走遍每一條邊並回到起點,輸出待選的邊數量和選的邊的起點和終點,不行的話輸出NO

思路:歐拉回路滿足題意,而滿足歐拉回路的充要條件是每個點的度都為偶數(無向圖)。所以先記下每個點的度數,用待選的邊建圖,然後開始深搜,可以考慮當前節點所連的下個結點的度數如果不是偶數那麼這條邊肯定要選。搜完以後判斷是不是每個點的度都是偶數。

#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
int du[300000+10],vis[300000+10];
vector<int>ve[300000+10];
int ans[300000+10][2],tot=0;
void dfs(int u,int p)
{
    if(vis[u])return;
    vis[u]=1;
    for(int i=0;i<ve[u].size();i++)
    {
        dfs(ve[u][i],u);
        if(ve[u][i]!=p&&du[ve[u][i]]==1)//如果當前點不是父親並且度數為偶數
        {
            ans[tot][0]=u;
            ans[tot][1]=ve[u][i];
            tot++;//記錄答案 新增一條u->ve[u][i]的邊
            du[u]++;
            du[u]%=2;
            du[ve[u][i]]=0;
        }
    }
}
int main()
{
    int n,m,k,u,v;
    scanf("%d%d%d",&n,&m,&k);
    memset(du,0,sizeof du);
    memset(vis,0,sizeof vis);
    for(int i=0;i<m;i++){
        scanf("%d%d",&u,&v);
        du[u]++;du[u]%=2;
        du[v]++;du[v]%=2;
    }
    for(int i=0;i<k;i++){//建圖
        scanf("%d%d",&u,&v);
        ve[u].push_back(v);
        ve[v].push_back(u);
    }
    for(int i=1;i<=n;i++){
       if(!vis[i])dfs(i,i);
    }
    for(int i=1;i<=n;i++){
        if(du[i]==1)return 0*printf("NO\n");
    }
    printf("YES\n%d\n",tot);
    for(int i=0;i<tot;i++){
        printf("%d %d\n",ans[i][0],ans[i][1]);
    }
    return 0;
}