題目:有n 個長為m+1 的字符串,如果某個字符串的最后m 個字符與某個字符串的前m 個字符匹配,則兩個字符串可以聯接,
問這n 個字符串最多可以連成一個多長的字符串,如果出現循環,則返回錯誤。
這個題目轉化為圖來做,設每個字符串看做一個頂點,如果(u,v)滿足u的后m個字符和v的前m個字符匹配,則連邊,權值設置為1即可。
然后針對建好的圖,進行拓撲排序,並檢查是否有環,如果有環,直接返回false,如果互換,則進行求最長路徑。
求最長路徑,我們可以根據floy來求,算法中直接將最短改為最長即可。下面是一種新的方法求最長路徑,用到拓撲排序的結果。
該思路的本質是利用動態規划,假設dist[v]表示以v結尾的最長路徑,那么dist[v]=max{dist[u]+edge[u][v], dist[v]}.其中u是
v的前驅,正好對應了拓撲排序的順序,我們按照拓撲順序依次就即可,由於每個入度為0的頂點都有可能產生最長的那條路徑,所以依次
求出來每個入度0頂點所產生的所有路徑。代碼入下:
//topret存放拓撲排序結果
int getMaxPath(int n)
{
memset(dist, 0, sizeof(dist));
int i = 0, j = 0, k = 0;
int maxd = 0;
for(i = 0; i < n; i++)
{
if(indegree[i] != 0)
continue;
//i為入度為0的頂點,作為本次的原點,計算到每個點的最長路徑
memset(dist, 0, sizeof(dist));
for(j = 0; j < n; j++)
{
//本次循環計算以j結尾的最長路徑
if( j == i)
continue;
for(k = 0; k < j; k++)
{
if(graph[topret[k]][topret[j]] == 1) //有路
{
if(dist[topret[k]] + 1 > dist[topret[j]])
dist[topret[j]] = dist[topret[k]] + 1;
}
}
if(dist[topret[j]] > maxd)
maxd = dist[topret[j]];
}
}
return maxd;
}
