用拓扑排序实现对环的判断
对于无向图用此方法
算法思想是:1)删除图中所有度<=1 的节点,以及与此节点相连的边,并且通过此边与此节点相连的节点的度减1
2)重复1 过程
如果图中还有节点的度>=2,那么存在环
对于有向图:
1)计算所有节点的入度,如果节点入度为0,则入栈
2)从栈中弹出节点,将与此节点相连的节点的入度减1,如果度为0,入栈
当栈空时,如果弹出栈的节点数少于节点总数,(或者说还有节点的度不为0)那么存在环
有向图中环的判断和个数计算,可以参考如下代码:
#include<iostream>
#include<cstring>
using namespace std;
int map[1000][1000];
int v[1000];
int n;
int num;
void dfs(int i){
if(!v[i])
v[i]=1;// v[i]=1;
for(int j=0;j<n;j++)
{
if(map[i][j]==1&&!v[j]){ //如果没访问,继续访问
dfs(j);
}
/**
* 这里有问题,不能这样做,因为所有访问的节点都会加一,并不是最先访问的节点才加一
* 如果能做到对于一个图,将最先遍历的节点记录下来,如果此第一节点访问两次,那么才可以判断
* 现在没有做这样的判断,有问题
* 对于有向图可以采用这种方法
*/
else if(map[i][j]==1&&v[j]) //已经访问过的节点,访问次数加1,但不递归深度
{
v[j]++;
}
}
}
void dfsGra(){
num=0;
for(int i=0;i<n;i++)
if(!v[i]){
dfs(i);
num++;//count 记录联通分量个数
}
}
void countCircle()
{
int cnt=0;
for(int i=0;i<n;i++)
{
cout<<v[i]<<" ";
if(v[i]>=2)
cnt++;
}
cout<<"图中包含"<<cnt<<"个环."<<endl;
}
int main()
{
int k,t,f;
cin>>n>>k;
memset(map,0,sizeof(map));
memset(v,0,sizeof(v));
while(k--)
{
cin>>f>>t;
map[f-1][t-1]=1;
}
dfsGra();
cout<<"有连通分量"<<num<<"个"<<endl;
countCircle();
return 0;
}
参考:http://www.myexception.cn/arithmetic/260798.html
求一个n+2序列中,n个数字为出现偶数次的,另外两个数字出现奇数(1)次。求出现奇数次的两个数字。
#include<iostream>
#include<cstring>
using namespace std;
void printTwoSingle(int data[],int n)
{
int s=0;
for(int i=0;i<n;i++)
s^=data[i];
int temp=s;
int k=0;
while(temp&1==0)
{
temp=temp>>1;
k++; //第k位首次出现1
}
int a=0;
int b=0;
for(int i=0;i<n;i++)
{
if((data[i]>>k)&1)
a^=data[i];
else
b^=data[i];
}
cout<<"两个单独的数分别是"<<a<<":"<<b<<endl;
}
int main()
{
int data[10]={1,1,2,2,3,3,4,4,5,6};
int n=10;
printTwoSingle(data,n);
return 0;
}
求一个字符串(包含重复)的所有排列
#include <iostream>
#include <cstring>
using namespace std;
#define N 4
void Swap(char *pa, char *pb);
void FullPermutation(char *str, int k, int n);
int IsAppeared(char *str, char t, int begin, int end);
char str[N+1] = "ADCD";
int main()
{
FullPermutation(str, 0, N);
return 0;
}
void Swap(char *pa, char *pb)
{
if(pa != pb)
{
char tmp = *pa;
*pa = *pb;
*pb = tmp;
}
}
//判断字符t在字符串的下标begin到end处是否出现过
int IsAppeared(char *str, char t, int begin, int end)
{
for(int j=begin; j<=end; ++j)
{
if(t == str[j])
return 1;
}
return 0;
}
/*对字符串进行全排列,注意该函数处理了字符重复的情况,字符重复的情况有两种:
1. str[i]本身和后面的str[k]相同
2. str[k]在k+1到i-1的下标之间已经出现过(用IsAppeared()函数去判断)
*/
void FullPermutation(char *str, int k, int n)
{
if(k == n)
{
cout<<str<<endl;
return;
}
for(int i=k; i<n; ++i)
{
if(i!=k && (str[i]==str[k]) || IsAppeared(str,str[i],k+1,i-1)) 用以处理元素重复的情况
continue;
Swap(str+k, str+i);
FullPermutation(str, k+1, n);
Swap(str+k, str+i);
}
}
#include<iostream>
#include<cstring>
using namespace std;
void swap(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
}
void permutationString(char s[],int start){
int len=strlen(s);
if(start==len)
{
for(inti=0;i<len;i++)
cout<<s[i]<<" ";
cout<<endl;
}
for(int i=start;i<len;i++)
{
swap(s[start],s[i]);
permutationString(s,start+1);
swap(s[start],s[i]);
}
}
void permutation(char s[])
{
if(s==NULL)
return;
permutationString(s,0);
}
int main()
{
char s[]="abc";
permutation(s);
}
同样问题的复习:八皇后问题
int g_number = 0;
bool Check(int ColumnIndex[], int length)
{
for(int i = 0; i < length; ++ i)
{
for(int j = i + 1; j < length; ++ j)
{
if((i - j ==ColumnIndex[i] - ColumnIndex[j])
|| (j - i ==ColumnIndex[i] - ColumnIndex[j]))
return false;
}
}
return true;
}
void PrintQueen(int ColumnIndex[], int length)
{
printf("Solution %d\n", g_number);
for(int i = 0; i < length; ++i)
printf("%d\t",ColumnIndex[i]);
printf("\n");
}
void Permutation(int ColumnIndex[], int length, int index)
{
if(index == length)
{
if(Check(ColumnIndex, length))
{
++ g_number;
PrintQueen(ColumnIndex,length);
}
}
else
{
for(int i = index; i < length; ++ i)
{
int temp =ColumnIndex[i];
ColumnIndex[i] =ColumnIndex[index];
ColumnIndex[index] =temp;
Permutation(ColumnIndex,length, index + 1);
temp =ColumnIndex[index];
ColumnIndex[index] =ColumnIndex[i];
ColumnIndex[i] = temp;
}
}
}
void EightQueen()
{
const int queens = 8;
int ColumnIndex[queens];
for(int i = 0; i < queens; ++ i)
ColumnIndex[i] =i+1; // 初始化
Permutation(ColumnIndex, queens,0);
}
int main()
{
EightQueen();
return 0;
}
自己的代码
#include<iostream>
#include<cstring>
using namespace std;
int num=0;
void swap(int &a,int &b)
{
char temp=a;
a=b;
b=temp;
}
bool isCheck(int s[],int len)
{
bool flag=true;
for(int i=0;i<len;i++)
{
for(intj=i+1;j<len;j++)
{
if((i-j)==(s[i]-s[j])||(i-j)==(s[j]-s[i]))
flag=false;
}
}
return flag;
}
void permutationString(int s[],int start,int len){
if(start==len&&isCheck(s,len))
{
num++;
for(int i=0;i<len;i++)
cout<<s[i]<<" ";
cout<<endl;
}
for(int i=start;i<len;i++)
{
swap(s[start],s[i]);
permutationString(s,start+1,len);
swap(s[start],s[i]);
}
}
void permutation(int s[],int len)
{
if(s==NULL||len<=0)
return;
permutationString(s,0,len);
}
int main()
{
int s[]={1,2,3,4,5,6,7,8};
permutation(s,8);
cout<<num<<endl;
}