实验六图的应用(通信网络)

应用图的ADT的物理实现来解决图的应用问题。

某国的军队由N个部门组成,为了提高安全性,部门之间建立了M条通路,每条通路只能单向传递信息,即一条从部门a到部门b的通路只能由a向b传递信息。信息可以通过中转的方式进行传递,即如果a能将信息传递到b,b又能将信息传递到c,则a能将信息传递到c。一条信息可能通过多次中转最终到达目的地。
由于保密工作做得很好,并不是所有部门之间都互相知道彼此的存在。只有当两个部门之间可以直接或间接传递信息时,他们才彼此知道对方的存在。部门之间不会把自己知道哪些部门告诉其他部门。
在这里插入图片描述

上图中给了一个4个部门的例子,图中的单向边表示通路。部门1可以将消息发送给所有部门,部门4可以接收所有部门的消息,所以部门1和部门4知道所有其他部门的存在。部门2和部门3之间没有任何方式可以发送消息,所以部门2和部门3互相不知道彼此的存在。
现在请问,有多少个部门知道所有N个部门的存在。或者说,有多少个部门所知道的部门数量(包括自己)正好是N。

【输入形式】

输入的第一行包含两个整数N, M,分别表示部门的数量和单向通路的数量。所有部门从1到N标号。
接下来M行,每行两个整数a, b,表示部门a到部门b有一条单向通路。

【输出形式】

输出一行,包含一个整数,表示答案。

【样例输入】

4 4
1 2
1 3
2 4
3 4

【样例输出】

2

【样例说明】

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

【评测用例规模与约定】

所有的评测用例,1 ≤ N ≤ 10,1 ≤ M ≤ 20;

#ifndef Graph_h
#define Graph_h
#include <stdio.h>
template <typename VertexType>
class Graph
{
private:
    void operator=(const Graph&) {}  // Protect assignment
    Graph(const Graph &) {} // Protect copy constructor
public:
    Graph(){}
    virtual ~Graph() {}
    virtual void Init(int n) =0;
    //return thr number of vertices and edges
    virtual int n() =0;
    virtual int e() =0;
    // Return v's first neighbor
    virtual int first(int v) =0;
    // Return v's next neighbor 
    virtual int next(int v, int w) =0;
    virtual void setType(bool flag)=0;
    virtual bool getType()=0;
    virtual int locateVex(VertexType u) =0;
    virtual VertexType getVex(int v)=0;
    virtual void putVex(int v,VertexType value) =0;
    // Set the weight for an edge (v1,v2)
    virtual void setEdge(int v1, int v2, int wght) =0;
    // Delete an edge
    virtual void delEdge(int v1, int v2) =0;
    virtual bool isEdge(int i, int j) =0;
    virtual int weight(int v1, int v2) =0;
    // Get and Set the mark value for a vertex 
    virtual int getMark(int v) =0;
    virtual void setMark(int v, int val) =0;
    virtual void DFS(int v)=0;
    virtual void BFS(int v)=0;
};
#endif 
#ifndef Graphl_h
#define Graphl_h
#include "Link.h"
#include "LList.h"
#include "Graph.h"
#include <queue>
#define MAX_VERTEX_NUM 40
#define UNVISITED 0
#define VISITED 1
#define ERROR -1
// Edge class for Adjacency List graph representation
class Edge
{
private:
    int vert, wt;
public:
    Edge() { vert = -1; wt = -1; }
    Edge(int v, int w) { vert = v; wt = w; }
    int vertex() { return vert; }
    int weight() { return wt; }
};
// Overload for the Edge << operator 
/*ostream& operator << (ostream& s, Edge e)
{
    return s << "(" << e.vertex() << ", " << e.weight() << ")";  
}*/
template <typename VertexType>
class Graphl : public Graph<VertexType>
{
private:
    LList<Edge>** vertex; // List headers
    int numVertex, numEdge;
    int *mark; // Pointer to mark array
    bool undirected;
    VertexType vexs[MAX_VERTEX_NUM];
public:
    int Out(int i)
    {
        return vertex[i]->length();
    }
    Graphl(int numVert)   { Init(numVert); }
    Graphl()
    {
        delete [] mark; // Return dynamically allocated memory
        for (int i=0; i<numVertex; i++)
            delete [] vertex[i];
        delete [] vertex;
    }
    void Init(int n)
    {
        int i;
        numVertex = n;
        numEdge = 0;
        mark = new int[n];
        for (i=0; i<numVertex; i++)
            mark[i] = UNVISITED;
        vertex =new LList<Edge>*[numVertex];
        for (i=0; i<numVertex; i++)
            vertex[i] = new LList<Edge>();
    }
    int n() { return numVertex; }
    int e() { return numEdge; }
    int first(int v)
    { // Return first neighbor of "v"
        if (vertex[v]->length()==0)
            return numVertex;      // No neighbor 
        vertex[v]->moveToStart();
        Edge it = vertex[v]->getValue();
        return it.vertex();
    }
    // Get v's next neighbor after w 
    int next(int v, int w)
    {
        Edge it;
        if(isEdge(v,w))
        {
            if ((vertex[v]->currPos()+1)<vertex[v]->length())
            {
                vertex[v]->next();
                it = vertex[v]->getValue();
                return it.vertex();
            }
        }
        return n(); // No neighbor 
    }
    void setType(bool flag)
    {
        undirected=flag;
    }
    bool getType(){ return undirected;}
    
    int locateVex(VertexType u)
    {
        for(int i=0;i<numVertex;i++)
        {
            if(u==vexs[i])
                return i;
        }
        return -1;
    }
    VertexType getVex(int v)  {return vexs[v];}
    void putVex(int v,VertexType value)  {vexs[v]=value;}
    // Set edge (i, j) to "weight"
    void setEdge(int i, int j, int weight)
    {
        if(weight<=0)
        {
            cout<<"May not set weight to 0\n";
            return ;
        }
        Edge currEdge(j, weight);
        if (isEdge(i, j))
        { // Edge already exists in graph 
            vertex[i]->remove();
            vertex[i]->insert(currEdge);
        }
        else
        { // Keep neighbors sorted by vertex index 
            numEdge++;
            for (vertex[i]->moveToStart();vertex[i]->currPos() < vertex[i]->length();vertex[i]->next())
            {
                Edge temp = vertex[i]->getValue();
                if (temp.vertex() >j)  break;
            }
            vertex[i]->insert(currEdge);
            if(undirected)
            {
                Edge currEdge(i, weight);
                for (vertex[j]->moveToStart();vertex[j]->currPos() < vertex[j]->length();vertex[j]->next())
                {
                        Edge temp = vertex[j]->getValue();
                        if (temp.vertex() > i) break;
                }
                vertex[j]->insert(currEdge);
            }
        }
        
    }
    void delEdge(int i, int j)
    {
        if (isEdge(i,j))
        {
            vertex[i]->remove();
            numEdge--;
        }
        if(undirected)
        {
            if (isEdge(j,i))
            {
                vertex[j]->remove();
                numEdge--;
            }
        }
    }
    bool isEdge(int i, int j)
    {
        Edge it;
        for (vertex[i]->moveToStart();vertex[i]->currPos() < vertex[i]->length();vertex[i]->next())
        {            // Check whole list 
            Edge temp = vertex[i]->getValue();
            if (temp.vertex() ==j) return true;
        }
        return false;
    }
    int weight(int i, int j)
    { // Return weight of (i, j) 
        Edge curr;
        if (isEdge(i, j))
        {
            curr = vertex[i]->getValue();
            return curr.weight();
        }
        else return 0;
    }
    int getMark(int v) { return mark[v]; }
    void setMark(int v, int val) { mark[v] = val; }
    void DFS(int v)
    {
        setMark(v,VISITED);
        cout<<getVex(v)<<' ';
        for(int i=first(v);i<n();i=next(v,i))
        {
            if(getMark(i)==UNVISITED)
            {
                DFS(i);
            }
        }
    }
    void BFS(int v)
    {
        queue<int> q;
        setMark(v,VISITED);
        //cout<<getVex(v)<<' ';
        q.push(v);
        while(!q.empty())
        {
            v=q.front();
            q.pop();
            for(int i=first(v);i<n();i=next(v,i))
            {
                if(getMark(i)==UNVISITED)
                {
                    setMark(i,VISITED);
                    //cout<<getVex(i)<<' ';
                    q.push(i);
                }
            }
        }
        //cout<<endl;
    }
};
#endif 
#ifndef Link_h
#define Link_h
#include <iostream>
template <typename E> class Link
{
public:
    E element;
    Link *next;
    Link(const E& elemval, Link* nextval =NULL)
    {
        element = elemval;
        next = nextval;
    }
    Link(Link* nextval =NULL)
    { next = nextval; }
};
#endif 
#ifndef LList_h
#define LList_h
#include "Link.h"
#include "List.h"
#include<iostream>
using namespace std;
template <typename E> class LList: public List<E>
{
private:
    Link<E>* head;
    Link<E>* tail;
    Link<E>* curr;
    int cnt;
    void init()
    {
        curr = tail = head = new Link<E>;
        cnt = 0;
    }
    void removeall()
    {
        // Return link nodes to free store
        while(head != NULL)
        {
            curr = head;
            head = head->next;
            delete curr;
        }
    }
public:
    LList(int size=100) { init(); }
    ~LList() { removeall(); }
    void clear() { removeall(); init(); }
    void insert(const E& it)
    {
        curr->next = new Link<E>(it, curr->next);
        if (tail == curr)
            tail = curr->next;
        cnt++;
    }
    void append(const E& it)
    {
        tail = tail->next = new Link<E>(it, NULL);
        cnt++;
    }
    E remove()
    {
        if(curr->next==NULL)
            return curr->element;;
        E it = curr->next->element;
        Link<E>* ltemp = curr->next;
        if (tail == curr->next)
            tail = curr;
        curr->next = curr->next->next;
        delete ltemp;
        cnt--;
        return it;
    }
    void moveToStart() { curr = head; }
    void moveToEnd(){ curr = tail; }
    void prev()
    {
        if (curr == head) return;
        Link<E>* temp = head;
        // March down list until we find the previous element
        while (temp->next!=curr) temp=temp->next;
        curr = temp;
    }
    void next()
    {
        if (curr != tail)
            curr = curr->next;
        
    }
    int length() const  { return cnt; }
    int currPos() const
    {
        Link<E>* temp = head;
        int i;
        for (i=0; curr != temp; i++)
            temp = temp->next;
        return i;
    }
    void moveToPos(int pos)
    {
        if ((pos>=0)&&(pos<=cnt))//"Position out of range"
        {
            curr = head;
            for(int i=0; i<pos; i++) curr = curr->next;
        }
        
    }
    const E& getValue() const
    {
       
        return curr->next->element;
    }
    const E& getNo() const
    {
        return curr->next->No;
    }
    const E& getCode() const
    {
        return curr->next->Code;
    }
    void reverse()
    {
        // Reverse list contents
        if(head->next == NULL) return;
        // First, fix fence by pushing it forward one step
        //if (fence->next == NULL)
           // fence = head;
        //else fence = fence->next;
        // Now, reverse the list
        Link<E>* temp1 = head->next;
        Link<E>* temp2 = temp1->next;
        while (temp2 != NULL)
        {
            Link<E>* temp3 = temp2->next;
            temp2->next = temp1;
            temp1 = temp2;
            temp2 = temp3;

            cout<<endl;
        }
        head->next->next=NULL;
        head->next = temp1;
    }
};
#endif 
#ifndef List_h
#define List_h
template <typename E> class List {     // List ADT
private:
    void operator =(const List&) {}      // Protect assignment
    List(const List&) {}               // Protect copy constructor
public:
    List() {}
    virtual ~List() {}     // Base destructor
    virtual void clear() = 0;
    virtual void insert(const E& item) = 0;
    // Append an element at the end of the list.
    virtual void append(const E& item) = 0;
    virtual E remove() = 0;
    // Set the current position to the start of the list.
    virtual void moveToStart() = 0;
    // Set the current position to the end of the list.
    virtual void moveToEnd() = 0;
    virtual void prev() = 0;
    virtual void next() = 0;
    virtual int length() const = 0;
    // Return: The position of the current element.
    virtual int currPos() const = 0;
    virtual void moveToPos(int pos) = 0;
    // Return: The current element.
    virtual const E& getValue() const = 0;
   };
#endif 
#include <iostream>
#include "Graph.h"
#include "Graphl.h"
using namespace std;
int main( )
{
    int n,m,i,j;
    cin>>n>>m;
    Graphl<int> G(n);
    G.setType(0);
    for(i=0;i<n;i++)
        G.putVex(i,i+1);
    int u,v;
    for(i=0;i<m;i++)
    {
        cin>>u>>v;
        G.setEdge(u-1,v-1,1);
    }
    int a[n][n];
    for(i=0;i<n;i++)
    	for(j=0;j<n;j++)
   			 a[i][j]=0;
    for(i=0;i<n;i++)
    {
        G.BFS(i);
        for(j=0;j<n;j++)
        {
            if(G.getMark(j)==VISITED)
            {
                a[i][j]=1;
                a[j][i]=1;
            }
        }
        for(j=0;j<G.n();j++)
        {
            G.setMark(j,UNVISITED);
        }
    }
    int sum=0;
    for(i=0;i<n;i++)
    {
        int flag=1;
        for(j=0;j<n;j++)
        {
            if(a[i][j]==0)
            {
                flag=0;
                break;
            }
        }
        if(flag)
            sum++;
    }
    cout<<sum<<endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值