苦逼练代码!
# include<stdio.h>
# include<queue>
# include<stack>
using namespace std;
# define N 103
# define M 1003
int g[N][N];
int bpG[N][N];
int visit[N];
void initG()
{
memset(g,0,sizeof(g));
g[1][2]=1;
g[1][3]=1;
g[2][1]=1;
g[2][4]=1;
g[2][5]=1;
g[3][1]=1;
g[3][6]=1;
g[3][7]=1;
g[4][2]=1;
g[4][6]=1;
g[4][8]=1;
g[5][2]=1;
g[5][6]=1;
g[5][7]=1;
g[6][3]=1;
g[6][4]=1;
g[6][5]=1;
g[7][3]=1;
g[7][5]=1;
g[8][4]=1;
g[9][10]=1;
g[9][11]=1;
g[10][9]=1;
g[11][9]=1;
g[11][12]=1;
g[12][11]=1;
}
void initBiPartionG()
{
memset(bpG,0,sizeof(bpG));
bpG[1][2]=1;
bpG[1][4]=1;
bpG[2][1]=1;
bpG[2][3]=1;
bpG[2][5]=1;
bpG[3][1]=1;
bpG[3][2]=1;
bpG[4][1]=1;
bpG[4][7]=1;
bpG[5][2]=1;
bpG[5][6]=1;
bpG[5][8]=1;
bpG[6][5]=1;
bpG[7][4]=1;
bpG[7][8]=1;
bpG[8][5]=1;
bpG[8][7]=1;
}
void BFS(int startNode)
{
int curNode,i,n=13;//只考虑前12个节点
queue<int> q;
q.push(startNode);
visit[startNode]=1;//加入队列时就设置visit
while(!q.empty())
{
curNode=q.front();
q.pop();
printf("%d ", curNode);
for(i=1;i<n;i++)
{
if(g[curNode][i]==1 && visit[i]==0)
{
q.push(i);
visit[i]=1;//加入队列时就设置visit
}
}
}
}
void DFS(int startNode)
{
int curNode,i,n=13;//只考虑前12个节点
stack<int> s;
s.push(startNode);
//visit[startNode]=1;
while(!s.empty())
{
curNode=s.top();
s.pop();
if(visit[curNode]==1)
{
continue;
}
visit[curNode]=1;//退出队列时【才需要】设置visit
printf("%d ", curNode);
for(i=1;i<n;i++)
{
if(g[curNode][i]==1 && visit[i]==0)
{
s.push(i);
//visit[i]=1;
}
}
}
}
void Topology()//假设小id指向大id,将无向图转换为有向图无环图(DAG)
{
int i,j,k,n=9;//只考虑前8个节点
int inCome[9];
memset(inCome,0,sizeof(inCome));
for(i=1;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(g[i][j]==1)
{
inCome[j]++;
}
}
}
int visit[9];
memset(visit,0,sizeof(visit));
for(i=1;i<n;i++)//依次找到第i个节点,方法如下:
{
//for(j=1;j<n;j++)//依次扫描inCome的每个元素
for(j=n-1;j>=1;j--)//为了不让结果是1-8,我们从大id的节点开始扫描
{
if(inCome[j]==0 && visit[j]==0)
{
printf("%d ", j);
visit[j]=1;
for(k=1;k<n;k++)
{
if(g[j][k]==1)
{
inCome[k]--;
}
}
break;
}
}
}
//正常的思路是使用队列,保存目前income=0的点,然后出一次队,邻接点的income减1,如果减1后income变为0,则入队;while(!queue.empty())。
printf("\n");
memset(inCome,0,sizeof(inCome));
for(i=1;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(g[i][j]==1)
{
inCome[j]++;
}
}
}
queue<int> q;
q.push(1);
while(!q.empty())
{
k=q.front();
q.pop();
printf("%d ", k);
for(i=k+1;i<n;i++)
{
if(g[k][i]==1)
{
inCome[i]--;
if(inCome[i]==0)
{
q.push(i);
}
}
}
}
}
void IsBiPartion(int g[][N])//本质和BFS一样,只不过要识别哪些点位于哪一层
{
int i,j,curLevel=-1,curNode,n=9;//只考虑前8个节点
int visitLevel[9];
memset(visitLevel,0,sizeof(visitLevel));
queue<int> q;
q.push(curLevel);//增加标识层节点
q.push(1);
visitLevel[1]=curLevel;
while(!q.empty())
{
curNode=q.front();
q.pop();
if(curNode<0)//当前是 标识层节点
{
curLevel--;//层数减1,由“-1”层变成“-2”层
q.push(curLevel);//在队列中增加标识下一层的节点
curNode=q.front();
q.pop();
if(curNode<0)//如果在一个标识层节点 后面紧跟着 另一个标识层节点,说明遍历结束
{
break;
}
}
printf("第【%d】层==>%d\n", -visitLevel[curNode], curNode);//输出每一而node的访问层
for(i=1;i<n;i++)
{
if(g[curNode][i]==1 && visitLevel[i]==0)
{
q.push(i);
visitLevel[i]=curLevel;
}
}
}
//遍历所有的边,看这些边的两个端点的层数有没有都是【同奇同偶】的情况,如果有,说明set内部出现了边,表示不可二分,否则可二分
for(i=1;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(g[i][j]==1 && (visitLevel[i]%2)==(visitLevel[j]%2))
{
printf("not a BiPartion graph!\n");
return;
}
}
}
printf("is a BiPartion graph!\n");
}
int main()
{
int i,n=13;
initG();
printf("BFS:\n");
memset(visit,0,sizeof(visit));
for(i=1;i<n;i++)
{
if(visit[i]==0)
{
BFS(i);
}
}
printf("\n");
printf("BFS:\n");
memset(visit,0,sizeof(visit));
for(i=1;i<n;i++)
{
if(visit[i]==0)
{
DFS(i);
}
}
printf("\n");
printf("Topology:\n");
memset(visit,0,sizeof(visit));
Topology();
printf("\n");
printf("IsBiPartion:\n");
IsBiPartion(g);
printf("\n");
printf("IsBiPartion:\n");
initBiPartionG();
IsBiPartion(bpG);
printf("\n");
return 0;
}