问题描述
试题编号: | 201709-4 |
试题名称: | 通信网络 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 某国的军队由N个部门组成,为了提高安全性,部门之间建立了M条通路,每条通路只能单向传递信息,即一条从部门a到部门b的通路只能由a向b传递信息。信息可以通过中转的方式进行传递,即如果a能将信息传递到b,b又能将信息传递到c,则a能将信息传递到c。一条信息可能通过多次中转最终到达目的地。 输入格式 输入的第一行包含两个整数N, M,分别表示部门的数量和单向通路的数量。所有部门从1到N标号。 输出格式 输出一行,包含一个整数,表示答案。 样例输入 4 4 样例输出 2 样例说明 部门1和部门4知道所有其他部门的存在。 评测用例规模与约定 对于30%的评测用例,1 ≤ N ≤ 10,1 ≤ M ≤ 20; |
最初提交的代码只有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;
}