///////////////////////////////////////////////////////////////////////////////////////////////////////
作者:tt2767
聲明:本文遵循以下協議自由轉載-非商用-非衍生-保持署名|Creative Commons BY-NC-ND 3.0
查看本文更新與討論請點擊:http://blog.csdn.net/tt2767
鏈接被刪請百度: CSDN tt2767
///////////////////////////////////////////////////////////////////////////////////////////////////////
這題值得學習的幾點:
1.輸入匹配的代碼十分優美!
2.把A+,A-映射成2n,2n+1做,然後通過(2n)^1 = 2n+1 , (2n+1)^1 = 2n 來反轉,不得不說十分精妙!
題解:由於正方形是無限的,把要去連接編號與被鏈接的正方形上的其他可擴展編號看成節點,被鏈接的正方形看成邊,尋找次有向圖的環。
題目中的例子:
A- |->->->->->->->->->->A+|->->->->->->->->(A+,A+,00)
要連接的節點————兩正方形連接點————被鏈接的正方形的其他節點
#include<cstdio>
#include<cstring>
int G[60][60];
int vis[60];
//把A+-變成2n和2n+1
int ID(char x, char y);
//這函數表示一個接口接到u上後成轉換成的其他接口
//利用(2n)^1 = 2n+1 , (2n+1)^1 = 2n 來反轉
void cont(char x1,char x2,char y1,char y2);
bool dfs(int u);
bool cyc();
int main()
{
int n;
while(scanf("%d",&n) == 1 && n)
{
memset(G,'\0',sizeof(G));
memset(vis,0,sizeof(vis));
for(int i = 0 ; i < n ; i++)
{
char s[9];
scanf("%s",s);
for(int j = 0 ; j < 4 ; j++)
for(int k = 0 ; k < 4 ; k++)
if(j != k) //對每個邊都與其他非自身的邊連接
cont(s[j*2],s[j*2+1],s[k*2],s[k*2+1]);
}
if(cyc())
puts("unbounded");//這個纔是無限的。。。
else
puts("bounded");
}
return 0;
}
int ID(char x, char y)
{
return (x-'A')*2 + (y == '+' ? 0 : 1);
}
void cont(char x1,char x2,char y1,char y2)
{
if(x1 == '0' || y1 == '0') return ;
int u = ID(x1,x2)^1 ;
int v = ID(y1,y2);
G[u][v]++;
}
bool dfs(int u)
{
vis[u] = -1;
for(int i = 0 ; i < 52 ; i++)
{
if(G[u][i])
{
if(vis[i] < 0) return true;
else if(!vis[i] && dfs(i)) return true;
}
}
vis[u] = 1;
return false;
}
bool cyc()
{
for(int i = 0 ; i < 52 ; i++)
if(!vis[i] && dfs(i))
return true;
return false;
}