1. 程式人生 > >【NOJ1593、1594、1595】【並查集三連】朋友敵人關係

【NOJ1593、1594、1595】【並查集三連】朋友敵人關係

1593.並查集(一)

時限:1000ms 記憶體限制:10000K  總時限:3000ms

描述

一個城市中有n個人,其中一些人是朋友關係,同時他們都認為:朋友的朋友是朋友,現在任給兩個人,問他們是否是朋友關係。

輸入

先輸入兩個正整數n和m(均小於1000),表示城市裡有n個人,並且將給出m對朋友關係,接下來的m行每行給出兩個0~n-1之間的整數,表示這兩個人是朋友關係。 最後一行再輸入兩個0~n-1之間的整數,問他們是否是朋友關係。

輸出

是朋友關係則輸出"Yes",否則輸出"No"。

#include <iostream>

using namespace std;

int a[1000];    //儲存並查集
int n,m;

int fsearch(int x); //返回結點x的根節點

int main()
{
    //輸入資料
    cin>>n>>m;

    for(int i=0;i<n;i++)
    {
        a[i]=i;    //初始時每個人只和自己做朋友
    }

    int x,y;    //是朋友關係的兩個人
    int kx,ky;  //根節點
    for(int i=0;i<m;i++)
    {
        cin>>x>>y;
        //cout<<x<<y;
        kx=fsearch(x);  //x的根節點
        ky=fsearch(y);  //y的根結點
        a[ky]=kx;       //相連
    }

    //輸出資料
    cin>>x>>y;
    kx=fsearch(x);  //x的根節點
    ky=fsearch(y);  //y的根結點
    if(kx==ky)
    {
        cout<<"Yes"<<endl;
    }
    else
    {
        cout<<"No"<<endl;
    }
    return 0;
}

int fsearch(int x)
{
    int f=a[x];
    while(f!=a[f])  //若未找到根節點
    {
        f=a[f];     //繼續向上搜尋
    }
    a[x]=f; //更新a[x]的值,使他離根節點更近,方便下一次搜尋
    return f;
}

1594.並查集(二)

時限:1000ms 記憶體限制:10000K  總時限:3000ms

描述

一個城市中有一些犯罪團伙,共有n個人,有m條資訊同夥資訊,並且知道同夥的同夥是同夥,問共有多少個犯罪團伙。

輸入

先輸入兩個正整數n和m(均小於1000),表示城市裡有n個人,並且將給出m對朋友關係,接下來的m行每行給出兩個0~n-1之間的整數,表示這兩個人是朋友關係。

輸出

輸出犯罪團伙的個數。

#include <iostream>

using namespace std;

int a[1000];    //儲存並查集-犯罪團伙
int n,m;

int fsearch(int x); //返回x結點的根節點

int main()
{
    cin>>n>>m;

    for(int i=0; i<n; i++)  //初始化並查集
    {
        a[i]=i;
    }

    int x,y;
    int kx,ky;
    for(int i=0; i<m; i++)  //讀入資料
    {
        cin>>x>>y;

        kx=fsearch(x);
        ky=fsearch(y);
        a[ky]=kx;
    }

    int cnt=0;    //犯罪團伙個數
    for(int i=0; i<n; i++)
    {
        if(a[i]==i) //數根節點個數
        {
            cnt++;
        }
    }
    cout<<cnt<<endl;
    return 0;
}


int fsearch(int x)   //返回x結點的根節點
{
    int f=x;
    while(f!=a[f])
    {
        f=a[f];
    }

    a[x]=f; //使x結點直接指向其根節點

    return f;
}

1595.並查集(三)

時限:1000ms 記憶體限制:10000K  總時限:3000ms

描述

一個城市中有n個人,其中一些人是朋友關係,一些人之間是敵人關係,同時他們都認為:朋友的朋友是朋友,敵人的敵人是朋友,(注意:朋友的敵人不一定是敵人),現在任給兩個人,問他們是否是朋友關係。

輸入

先輸入兩個正整數n和m(均小於1000),表示城市裡有n個人,並且將給出m對朋友或敵人關係,接下來的m行每行三個整數,先給出一個整數0或1(0表示後面這兩個人是朋友,1表示是敵人),再給出兩個0~n-1之間的整數表示兩個人。 最後一行再輸入兩個0~n-1之間的整數,問這兩個人是否是朋友關係。

輸出

是則輸出"Yes",否則輸出"No"。

#include <iostream>

using namespace std;

int a[1000];    //朋友並查集
int b[1000][1000];      //儲存敵人關係
int n,m;

int fa_search(int x);   //返回並查集a裡x的根節點

void fa_add(int x, int y);  //將x和y新增成朋友關係
void fb_add(int x, int y);  //將x和y新增成敵人關係

void f_add(int x, int y);   //將y的敵人與x新增成朋友關係
                            //(敵人的敵人是朋友)

int main()
{
    cin>>n>>m;

    for(int i=0; i<n; i++)  //初始化並查集
    {
        a[i]=i;
    }

    int p,x,y;
    int kx,ky;
    for(int i=0; i<m; i++)  //輸入資料
    {
        cin>>p>>x>>y;
        if(p==0)    //x和y是朋友
        {
            fa_add(x, y);
        }
        else        //x和y是敵人
        {
            //在b中新增敵人關係
            fb_add(x, y);

            //y的所有敵人是x的朋友
            f_add(x, y);

            //x的所有敵人是y的朋友
            f_add(y, x);
        }
    }

    cin>>x>>y;
    kx=fa_search(x);
    ky=fa_search(y);
    if(kx==ky)              //輸出資料
    {
        cout<<"Yes"<<endl;
    }
    else
    {
        cout<<"No"<<endl;
    }

    return 0;
}

int fa_search(int x)    //返回並查集a裡x的根節點
{
    int f=a[x];
    while(f!=a[f])
    {
        f=a[f];
    }
    a[x]=f;     //更新a[x]
    return f;
}

void fa_add(int x, int y)   //將x和y新增成朋友關係
{
    int kx,ky;
    kx=fa_search(x);
    ky=fa_search(y);
    a[ky]=kx;
}

void fb_add(int x, int y)   //將x和y新增成敵人關係
{
    b[x][y]=1;
    b[y][x]=1;
}


void f_add(int x, int y)    //將y的敵人與x新增成朋友關係
{                           //(敵人的敵人是朋友)
    for(int i=0; i<n; i++)
    {
        if(i!=x&&i!=y)
        {
            if(b[y][i]==1)  //若y和i是敵人關係
            {
                fa_add(x,i);    //那麼x和i是朋友關係
            }
        }
    }
}

【後記】

1.並查集(四)吭哧半天沒寫出來,好氣啊,待續