我正在进行一项练习(自学): "显示如何确定有向图G是否包含通用链接 - 具有in-degree(V-1)(V是顶点数)的顶点和时间O(V)中的out-degree 0,给定G的邻接矩阵 我在这里写了代码:
int UniversalSink(const int *a, int N)
{
int i,j,i1,j1,q;
i=0;
i=0;
q=YES;
j=-1;
do
{
j++;
if (j==N)
break;
while ( (*(a+i*MAX+j)) ==0 )
{
j++;
if (j==N)
{
break;
}
}
if (j==N)
break;
q= YES;
for (; i<j; i++)
if ( (*(a+i*MAX+j)) ==0 )
{
i=j,j=i-1;
q= NO;
break;
}
if (q==NO)
continue;
q=YES;
/*
for (i=0; i<=j; i++ )
if (a[j][i] ==1 )
{
i=j;
q=NO;
ok=NO;
trai = NO;
break;
}
if (q==NO)
continue;
*/
q=YES;
for (i1= j+1; i1<N; i1++)
if ((*(a + i1*MAX +j)) ==0 )
{
i=i1, j=i-1;
q=NO;
break;
}
if (q==NO)
continue;
}
while (j<N);
{
i1=i;
for (j1=0; j1<N;j1++)
if ( (*(a + i1*MAX +j1 )) ==1 )
return -1;
j1=i;
for (i1=0; i1<N;i1++)
{
if (i1==j1)
continue;
if ( (*(a + i1*MAX +j1))==0)
return -1;
}
return i;
}
它需要一个N-N矩阵并返回通用接收器的位置(如果存在则为0到N-1,如果它不存在则为-1) 但是,我真的不知道它是否是O(V),事实上我不确定它是否总能计算出所需的结果 请帮助我,我花了整整一个晚上工作(也许我相当愚蠢)。并随意评论我的代码的任何其他方面(例如我似乎使用了太多的休息)
答案 0 :(得分:3)
您可以使用以下代码:
int DetectSink(matrix G, int V) {
int i = 0;
int j = 0;
while (i < V && j < V)
if (G[i][j])
i = i + 1;
else j = j + 1;
if (i < V && IsSink(G, i)) return i;
return -1;
}
如果k是通用接收器,那么第k个
邻接矩阵(G
)的行将是
全0,第k列全部
1s(G[k][k] = 0
除外)。
OBS:我们可以得出结论,最多只有一个接收器。
如果k
中存在univeral sink G
,那么最终,
我们定位(i = k, j)
或(i, j = k)
。
k
+---+---+---+---+---+
| | | 1 | | |
+---+---+---+---+---+
| | | 1 | | |
+---+---+---+---+---+
k | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+
| | | 1 | | |
+---+---+---+---+---+
| | | 1 | | |
+---+---+---+---+---+
如果我们在行k (j=k)
之前到达列k (i=k)
,
我们的算法优先于然后块,直到
(i = k, j = k)
,然后执行 else 块
直到(i = k, j = V)
。
在其他情况下,如果首先到达第k行
第k列,然后 else 块除外
while循环结束,直到(i = k, j = V)
。
最后,我们必须检查i
是否具有普遍性
下沉,因为我们知道水槽是否存在它是i
,
但我们不知道我们的算法是什么
如果通用接收器不在G
。
运行时间为O(V)
,因为每一步都是如此
我们会增加i
或j
,所以最多2V
操作发生者。 IsSink
部分为O(V)
。
有一个很好的解决方案使用Divide&amp;征服:
在这个解决方案中,我们保留了一组候选人 通用水槽,我们在每一步都做成对 顶点并按顺序丢弃两个顶点中的一个 分析初始候选人的一半。