CSP之通訊網路(60分\100分)

Just Go For It Now發表於2018-09-14

問題描述

試題編號: 201709-4
試題名稱: 通訊網路
時間限制: 1.0s
記憶體限制: 256.0MB
問題描述:

問題描述

  某國的軍隊由N個部門組成,為了提高安全性,部門之間建立了M條通路,每條通路只能單向傳遞資訊,即一條從部門a到部門b的通路只能由ab傳遞資訊。資訊可以通過中轉的方式進行傳遞,即如果a能將資訊傳遞到bb又能將資訊傳遞到c,則a能將資訊傳遞到c。一條資訊可能通過多次中轉最終到達目的地。
  由於保密工作做得很好,並不是所有部門之間都互相知道彼此的存在。只有當兩個部門之間可以直接或間接傳遞資訊時,他們才彼此知道對方的存在。部門之間不會把自己知道哪些部門告訴其他部門。

  上圖中給了一個4個部門的例子,圖中的單向邊表示通路。部門1可以將訊息傳送給所有部門,部門4可以接收所有部門的訊息,所以部門1和部門4知道所有其他部門的存在。部門2和部門3之間沒有任何方式可以傳送訊息,所以部門2和部門3互相不知道彼此的存在。
  現在請問,有多少個部門知道所有N個部門的存在。或者說,有多少個部門所知道的部門數量(包括自己)正好是N

輸入格式

  輸入的第一行包含兩個整數NM,分別表示部門的數量和單向通路的數量。所有部門從1到N標號。
  接下來M行,每行兩個整數ab,表示部門a到部門b有一條單向通路。

輸出格式

  輸出一行,包含一個整數,表示答案。

樣例輸入

4 4
1 2
1 3
2 4
3 4

樣例輸出

2

樣例說明

  部門1和部門4知道所有其他部門的存在。

評測用例規模與約定

  對於30%的評測用例,1 ≤ N ≤ 10,1 ≤ M ≤ 20;
  對於60%的評測用例,1 ≤ N ≤ 100,1 ≤ M ≤ 1000;
  對於100%的評測用例,1 ≤ N ≤ 1000,1 ≤ M ≤ 10000。

 

最初提交的程式碼只有60分,我仔細想了一下,主要原因還是在於每次搜尋過程都需要遍歷整個vector,以檢查是否存在重複元素,這也最終導致演算法的複雜度較高。後來我將向量G0換成陣列之後,成功解決了超時的問題,拿到了滿分。

下面分別是60分程式碼和滿分程式碼。

(60分)

#include <stdio.h>
#include <algorithm>
#include <queue>
#include <cstring>
#include <vector>
using namespace std;

#define MAX 1005

vector<int> G[MAX];
vector<int> G0[MAX];
//int G[MAX][MAX];
//int G0[MAX][MAX]
int vis[MAX];

int isok(int a,int b)
{
    vector<int>::iterator iter;
    iter=find(G0[a].begin(),G0[a].end(),b);
    if(iter!=G0[a].end()) return 0;
    else return 1;

}

void DFS(int s)
{
    queue<int> q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(isok(s,u)) G0[s].push_back(u);
        if(isok(u,s)) G0[u].push_back(s);
        for(int j=0;j<G[u].size();j++)
        {
            int v=G[u][j];
            if(vis[v]==0)
            {
                q.push(v);
                vis[v]=1;
            }
        }

    }
}
int main()
{
    int N,M;
    scanf("%d %d",&N,&M);
    int i,j;
    int a,b;
    for(i=0;i<M;i++)
    {
        scanf("%d %d",&a,&b);
        G[a].push_back(b);
    }
    for(i=1;i<=N;i++)
    {
        memset(vis,0,sizeof(vis));
        DFS(i);
    }
    int ans=0;
    for(i=1;i<=N;i++)
    {
        if(G0[i].size()==N)
        {
            ans++;
        }
    }
    printf("%d\n",ans);
    return 0;
}

(100分)

#include <stdio.h>
#include <algorithm>
#include <queue>
#include <cstring>
#include <vector>
using namespace std;

#define MAX 1005

vector<int> G[MAX];
int adj[MAX][MAX];
int vis[MAX];

//int isok(int a,int b)
//{
//    vector<int>::iterator iter;
//    iter=find(G0[a].begin(),G0[a].end(),b);
//    if(iter!=G0[a].end()) return 0;
//    else return 1;
//
//}

void DFS(int s)
{
    queue<int> q;
    q.push(s);
    vis[s]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        adj[s][u]=adj[u][s]=1;
        for(int j=0;j<G[u].size();j++)
        {
            int v=G[u][j];
            if(vis[v]==0)
            {
                q.push(v);
                vis[v]=1;
            }
        }

    }
}
int main()
{
    int N,M;
    scanf("%d %d",&N,&M);
    int i,j;
    int a,b;
    memset(adj,0,sizeof(adj));
    for(i=0;i<M;i++)
    {
        scanf("%d %d",&a,&b);
        G[a].push_back(b);
    }
    for(i=1;i<=N;i++)
    {
        memset(vis,0,sizeof(vis));
        if(vis[i]==0) DFS(i);
    }
    int ans=0;
    for(i=1;i<=N;i++)
    {
        for(j=1;j<=N;j++)
        {
            if(adj[i][j]==1&&adj[j][i]==1) continue;
            else break;
        }
        if(j==N+1) ans++;
    }
    printf("%d\n",ans);
    return 0;
}

 

相關文章