【基礎練習】【強連通tarjan】vijos1021-1023 Victoria的舞會系列題解

題目連接:https://vijos.org/p/Victoria%E7%9A%84%E8%88%9E%E4%BC%9A

這是一個圖論的系列題目,題目比較簡單,主要在於數據實在是弱···兩百個點暴搜都能過啊···

vijos用戶體驗還是不錯的 除了管理不太嚴格導致題解混亂 雖然二老闆在但也長期無人打理  如果照管好 這一定會是一個相當出色的OJ


1021 舞會1

這道題目其實就是簡單的統計 不多說 上代碼

//vijos1021 Victoria的舞會1 模擬
//copuright by ametake
#include
using namespace std;

int a[200+10];
int n,k,m;

int main()
{
    scanf("%d%d",&n,&k);
    int x=0;
    for (int i=1;i<=n;i++)
    {
        while (scanf("%d",&x)&&(x!=0)) a[i]++;
        if (a[i]>=k) m++;
    }
    printf("%d\n",m);
    return 0; 
} 

1022 舞會2

由於交流具有傳遞性 每個小組都是一個儘可能大的環 直接統計強連通分量個數即可

//vijos1022 Victoria的舞會2 tarjan
//copuright by ametake
#include
#include
#include
using namespace std;

const int maxn=200+10;
const int maxm=40000+10;
int n,m=0;
int hd[maxn],tt[maxm*2],nxt[maxm*2],et=0;
int dfn[maxn],low[maxn],sta[maxn],stp=0,dep=0;
bool ins[maxn];

inline int read()
{
    int a=0;
    char ch=getchar();
    while (ch<'0'||ch>'9')
    {
        ch=getchar();
    }
    while (ch>='0'&&ch<='9')
    {
        a=a*10+ch-'0';
        ch=getchar();
    }
    return a;
}

void add(int x,int y)
{
    et++;
    tt[et]=y;
    nxt[et]=hd[x];
    hd[x]=et;
}

void tarjan(int x)
{
    dfn[x]=low[x]=++dep;
    ins[x]=true;
    sta[++stp]=x;
    for (int i=hd[x];i!=0;i=nxt[i])
    {
        if (!dfn[tt[i]])
        {
            tarjan(tt[i]);
            low[x]=min(low[x],low[tt[i]]);
        }
        else if (ins[tt[i]])
        {
            low[x]=min(low[x],dfn[tt[i]]);
        }
    }
    if (dfn[x]==low[x])
    {
        int j;
        m++;
        do
        {
            j=sta[stp--];
            ins[j]=false;
        }while (j!=x);
    }
    return;
}

int main()
{
    n=read();
    for (int i=1;i<=n;i++)
    {
        int x=read();
        while (x)
        {
            add(i,x);
            x=read();
        }
    }
    for (int i=1;i<=n;i++)
    {
        if (!dfn[i])
        {
            tarjan(i);
        }
    }
    printf("%d\n",m);
    return 0;
}

1023 舞會3

這道題目做法很多樣 雖然題解裏說數據弱到粘第二題代碼都能過(太坑了吧!難道不存在一條鏈的情況嗎?!)但我還是老實寫了強連通縮點+統計入度

我們考慮什麼樣的情況可以不用通知呢?一個是環,因爲環內人可以互相通知,只需通知一個人就可以了,因此可以縮成一點;另一個是鏈,鏈起始點的人可以通知到這條鏈上所有人。

因此,做一次tarjan之後統計出度爲0的節點就可以了。但不知爲什麼,同樣的方法間諜網絡就T了= =

代碼:

//vijos1023 Victoria的舞會3 tarjan
//copuright by ametake
#include
#include
#include
using namespace std;

const int maxn=200+10;
const int maxm=40000+10;
int n,m=0,ans=0;
int hd[maxn],tt[maxm*2],nxt[maxm*2],et=0;
int dfn[maxn],low[maxn],sta[maxn],stp=0,dep=0;
bool ins[maxn],ru[maxn][maxn];
int inwhich[maxn],rudu[maxn];

inline int read()
{
    int a=0;
    char ch=getchar();
    while (ch<'0'||ch>'9')
    {
        ch=getchar();
    }
    while (ch>='0'&&ch<='9')
    {
        a=a*10+ch-'0';
        ch=getchar();
    }
    return a;
}

void add(int x,int y)
{
    et++;
    tt[et]=y;
    nxt[et]=hd[x];
    hd[x]=et;
}

void tarjan(int x)
{
    dfn[x]=low[x]=++dep;
    ins[x]=true;
    sta[++stp]=x;
    for (int i=hd[x];i!=0;i=nxt[i])
    {
        if (!dfn[tt[i]])
        {
            tarjan(tt[i]);
            low[x]=min(low[x],low[tt[i]]);
        }
        else if (ins[tt[i]])
        {
            low[x]=min(low[x],dfn[tt[i]]);
        }
    }
    if (dfn[x]==low[x])
    {
        int j;
        m++;
        do
        {
            j=sta[stp--];
            ins[j]=false;
            inwhich[j]=m;
        }while (j!=x);
    }
    return;
}

int main()
{
    n=read();
    for (int i=1;i<=n;i++)
    {
        int x=read();
        while (x)
        {
            add(i,x);
            x=read();
        }
    }
    for (int i=1;i<=n;i++)
    {
        if (!dfn[i])
        {
            tarjan(i);
        }
    }
    for (int i=1;i<=n;i++)
    {
        for (int j=hd[i];j!=0;j=nxt[j])
        {
            if ((inwhich[i]!=inwhich[tt[j]])&&(!ru[inwhich[i]][inwhich[tt[j]]]))
            {
                ru[inwhich[i]][inwhich[tt[j]]]=true;
                rudu[tt[j]]++;
            }
        }
    }
    for (int i=1;i<=m;i++) if (rudu[i]==0) ans++;
    printf("%d\n",ans);
    return 0;
}

——東籬把酒黃昏後,有暗香盈袖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章