图
表示:
邻接链表:稀疏图
邻接矩阵:稠密图,快判两个节点之间是否有边
bfs:
广度优先搜索树:既可用于有向和无向
所有与黑色节点相连接的节点都是以发现。
灰色不一定。颜色属性
最短路径
广度优先树
深度优先树:树边,前驱子图,深度优先树,深度优先森林
深度优先树不相交,树边
两个时间戳,一个纪录被发现,一个纪录完成了
u.d u.f在1到2|V|之间
解决括号化结构
递归靠压栈来完成
有向图有前向后向边横向边数边
无向图:无前向边和横向边
uva,10336
注意:
都是从输入流中读取数据,但功能有很大差别:
1 操作类型不同。
gets函数仅用于读入字符串。
scanf为格式化输出函数,可以读入任意C语言基础类型的变量值,而不是仅限于字符串(char*)类型。
2 截止字符不同。
gets函数固定的以换行符作为结尾,遇到换行符时结束输入。
scanf函数默认以空白函数结尾,同时可以对截止函数进行修改。
3 对截止字符处理不同。
gets函数会读入截止字符\n, 同时将\n自动替换为\0.
scanf遇到截止字符时不会继续读取,截止字符将存储于输入缓冲中。
4 返回值类型不同。
gets的返回值为char*型,当读入成功时会返回输入的字符串指针地址,出错时返回NULL。
scanf返回值为int型,返回实际成功赋值的变量个数,当遇到文件结尾标识时返回EOF。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 6 using namespace std; 7 8 char map[100][100]; 9 int sets[128]; 10 11 int dx[]={1,0,-1,0},dy[]={0,1,0,-1}; 12 13 void dfs(int x,int y,int m,int n,char c) 14 { 15 if(x<0 || x>=m || y<0 || y>=n || map[x][y]!=c) 16 return; 17 map[x][y]=0; 18 for(int k=0;k<4;k++) 19 { 20 dfs(x+dx[k],y+dy[k],m,n,c); 21 } 22 } 23 24 int main() 25 { 26 int t; 27 int m,n; 28 while(~scanf("%d",&t) && t) 29 for(int k=1;k<=t;k++) 30 { 31 scanf("%d %d",&m,&n); 32 33 int i,j; 34 for(i=0;i<m;i++) 35 scanf("%s",map[i]); //不能用gets() 36 //因为gets把接收回车并把'\n'转换为'\0' 37 //scanf不接收回车,放入下一行。而scanf函数可以识别空格结束。 38 //会比scanf多一列。。。 39 40 memset(sets,0,sizeof(sets)); 41 int maxs=0; 42 for(i=0;i<m;i++) 43 for(j=0;j<n;j++) 44 { 45 if(!sets[map[i][j]] && map[i][j]) 46 { 47 sets[map[i][j]]=1; 48 int count=0; 49 char temp=map[i][j]; 50 51 for(int p=0;p<m;++p) 52 for(int q=0;q<n;++q) 53 { 54 if(map[p][q]==temp) 55 { 56 dfs(p,q,m,n,temp); 57 count++; 58 } 59 } 60 sets[temp]=count; 61 if(maxs<count) 62 maxs=count; 63 64 } 65 } 66 printf("World #%d\n",k); 67 for(int i=maxs;i;--i) 68 for(int j=0;j<26;++j) 69 { 70 if(sets['a'+j]==i) 71 printf("%c: %d\n",'a'+j,i); 72 } 73 } 74 return 0; 75 }
uva,315
对于新手的我,刚刚把dfs和bfs看了一遍就过来做题目。大概知道具体的意识。但是解法就一脸懵逼。
于是去网上搜了一下。知道了是解强联通图/强联通分量的割点的问题。具体用tarjan模版套一套就好咯。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <sstream> 7 8 using namespace std; 9 10 int dfs_time; 11 int dfn[105],low[105]; 12 int ans; 13 vector<int> edge[105]; 14 15 void dfs(int cur,int parent) 16 { 17 bool flag=false; 18 int child=0; 19 dfn[cur]=low[cur]=++dfs_time; 20 21 22 for(int i=0;i<edge[cur].size();++i) 23 { 24 int nxt=edge[cur][i]; 25 if(!dfn[nxt]) 26 { 27 ++child; 28 dfs(nxt,cur); 29 low[cur]=min(low[cur],low[nxt]); 30 31 if(low[nxt]>=dfn[cur]) 32 flag=true; 33 } 34 else if(nxt!=parent) 35 low[cur]=min(low[cur],dfn[nxt]); 36 } 37 38 if((child>=2 || parent!=-1) && flag) 39 ++ans; 40 } 41 42 int main() 43 { 44 int n; 45 string line; 46 while(scanf("%d ",&n),n) //注意%d后面有一空格,输出啊。。。 47 { 48 ans=0; 49 dfs_time=0; //纪录时间戳 50 for(int i=0;i<=n;i++) 51 { 52 dfn[i]=0; 53 low[i]=0; 54 edge[i].clear(); 55 } 56 57 int a,b; 58 while(getline(cin,line)) 59 { 60 stringstream ss(line); //不确定输出用流解决。但是耗时 61 ss >> a; 62 if(!a) break; 63 while(ss >> b) 64 { 65 edge[a].push_back(b); 66 edge[b].push_back(a); 67 } 68 69 } 70 71 dfs(1,-1); 72 73 printf("%d\n",ans); 74 } 75 }
uva,104
g[i][j][p]表示进过p次交换的最大利率。其实就是模拟建图然后用求最短路的思想求出最大利率。
最后比较当存在一个值大1.01就找到。其输出也是folyd的一部分
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 5 using namespace std; 6 const int maxn=25; 7 8 int n; 9 double g[maxn][maxn][maxn]; 10 int d[maxn][maxn][maxn]; 11 12 void init() 13 { 14 memset(g,0,sizeof(g)); 15 int i,j; 16 17 for(i=0;i<n;i++) 18 for(j=0;j<n;j++) 19 { 20 if(i!=j) 21 { 22 scanf("%lf",&g[i][j][1]); 23 d[i][j][1]=i; 24 } 25 } 26 } 27 28 void print(int x,int y,int p) 29 { 30 if(p==0) 31 printf("%d",x+1); 32 else 33 { 34 print(x,d[x][y][p],p-1); 35 printf(" %d",y+1); 36 } 37 } 38 39 void Floyd() 40 { 41 int i,j,k,p; 42 for(p=1;p<n;p++) 43 { 44 for(k=0;k<n;k++) 45 for(i=0;i<n;i++) 46 for(j=0;j<n;j++) 47 { 48 if(g[i][k][p]*g[k][j][1]>g[i][j][p+1]+1e-9) 49 { 50 g[i][j][p+1]=g[i][k][p]*g[k][j][1]; 51 d[i][j][p+1]=k; 52 } 53 } 54 for(i=0;i<n;i++) 55 if(g[i][i][p+1]>1.01) 56 { 57 print(i,i,p+1); 58 printf("\n"); 59 return; 60 } 61 } 62 printf("no arbitrage sequence exists\n"); 63 } 64 65 int main() 66 { 67 while(~scanf("%d",&n)) 68 { 69 init(); 70 Floyd(); 71 } 72 return 0; 73 }
HDU,4401
dfs找到一个四周存在'#'的中心点并标记。然后bfs判断这个中心点是不是对的。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 6 using namespace std; 7 const int maxn=55; 8 int dx[]={1,-1,0,0},dy[]={0,0,1,-1}; 9 char ch[maxn][maxn]; 10 int vis[maxn][maxn]; 11 int center[maxn][maxn]; 12 int n; 13 int cnt; 14 15 struct Node 16 { 17 int x,y; 18 }q[11111]; 19 20 bool check(int x,int y) 21 { 22 if(x<0 || x>=n || y<0 || y>=n) return false; 23 if(vis[x][y]) return false; 24 if(ch[x][y]!='#') return false; 25 return true; 26 } 27 28 29 void dfs(int x,int y) 30 { 31 int num=0; 32 int xx,yy; 33 for(int i=0;i<4;i++) 34 { 35 xx=x+dx[i]; 36 yy=y+dy[i]; 37 if(check(xx,yy)) 38 { 39 num++; 40 vis[x][y]=1; 41 dfs(xx,yy); 42 } 43 } 44 if(num==3) 45 center[x][y]=1; 46 } 47 48 void bfs(int x,int y) 49 { 50 int head=0,tail=0; 51 q[head].x=x; 52 q[head++].y=y; 53 int cut=4; 54 vis[x][y]=1; 55 while(head!=tail) 56 { 57 int num=0; 58 Node t=q[tail++]; 59 Node tt; 60 for(int i=0;i<4;i++) 61 { 62 tt.x=t.x+dx[i]; 63 tt.y=t.y+dy[i]; 64 if(check(tt.x,tt.y)) 65 { 66 num++; 67 vis[tt.x][tt.y]=1; 68 q[head++]=tt; 69 } 70 } 71 if(num==1) cut++; 72 } 73 cut=cut/4; 74 if(cut*4+1==head) cnt++; 75 } 76 77 78 int main() 79 { 80 while(scanf("%d",&n),n) 81 { 82 memset(center,0,sizeof(center)); 83 cnt=0; 84 for(int i=0;i<n;i++) 85 scanf("%s",ch[i]); 86 87 memset(vis,0,sizeof(vis)); 88 for(int i=0;i<n;i++) 89 for(int j=0;j<n;j++) 90 { 91 if(!vis[i][j] && ch[i][j]=='#') 92 { 93 vis[i][j]=1; 94 dfs(i,j); 95 } 96 } 97 98 99 memset(vis,0,sizeof(vis)); 100 for(int i=0;i<n;i++) 101 for(int j=0;j<n;j++) 102 { 103 if(center[i][j] && !vis[i][j]) 104 { 105 memset(q,0,sizeof(q)); 106 bfs(i,j); 107 } 108 } 109 printf("%d\n",cnt); 110 } 111 return 0; 112 }
uva,260
黑的从上往下走横行,白的从左往右走纵行,每次走能走上下左右以及左上右下。
给你一盘下满的棋,问你那个赢。一开始写了个判断深度的,发现
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 5 using namespace std; 6 const int maxn=205; 7 int dx[]={-1,-1,0,0,1,1},dy[]={-1,0,-1,1,0,1}; 8 int n; 9 int cnt; 10 char map[maxn][maxn]; 11 12 13 int dfs(int x,int y,int n) 14 { 15 if(x==n) return 1; 16 if(x<0 || x>=n || y<0 || y>=n) return 0; 17 if(map[x][y]!='b') return 0; 18 map[x][y]='#'; 19 int max=0; 20 for(int i=0;i<6;i++) 21 { 22 max |=dfs(x+dx[i],y+dy[i],n); //不知道什么鬼 23 } 24 return max; 25 } 26 27 int main() 28 { 29 int k=1; 30 while(scanf("%d",&n),n) 31 { 32 int i; 33 int flag=0; 34 for(i=0;i<n;i++) 35 scanf("%s",map[i]); 36 for(i=0;i<n;i++) 37 { 38 if(map[0][i]=='b' && dfs(0,i,n)) 39 { 40 flag=1; 41 break; 42 } 43 } 44 if(!flag) 45 printf("%d W\n",k++); 46 else printf("%d B\n",k++); 47 } 48 return 0; 49 }
uva,469
不确定输入的强大。。。sscanf(str,"%d %d",&i,&j)再一次震撼~
给你一个网格盘有水和土地,再给你其中一个水格的坐标让你找出它附近共有多少个水格子,dfs八个方向深搜。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 6 using namespace std; 7 const int maxn=105; 8 int dx[]={-1,0,-1,-1,0,1,1,1},dy[]={-1,-1,0,1,1,-1,0,1}; 9 10 char map[maxn][maxn]; 11 int vis[maxn][maxn]; 12 int cnt; 13 14 void dfs(int x,int y) 15 { 16 if(x<0 || y<0 || !map[x][y]) return; 17 if(map[x][y]!='W') return; 18 if(vis[x][y]) return; 19 20 vis[x][y]=1;cnt++; 21 for(int i=0;i<8;i++) 22 dfs(x+dx[i],y+dy[i]); 23 } 24 25 int main() 26 { 27 int t; 28 int i,j; 29 char str[105]; 30 scanf("%d ",&t); 31 while(t--) 32 { 33 int n=0; 34 memset(map,0,sizeof(map)); 35 while(gets(str)) 36 { 37 if(str[0]=='\0') 38 break; 39 40 if(str[0]!='W' && str[0]!='L') 41 { 42 sscanf(str,"%d %d",&i,&j); 43 memset(vis,0,sizeof(vis)); 44 cnt=0; 45 dfs(i-1,j-1); 46 printf("%d\n",cnt); 47 } 48 else 49 sscanf(str,"%s",map[n++]); 50 } 51 if(t) 52 puts(""); 53 } 54 return 0; 55 }
uva,10596
加边减边,vis加加减减
前面写过一个判点是否全部在的,老是各种错误。。lld什么的
而且我试了一下,欧拉回路的判断条件:全是偶数度的点,或者终点和起点是奇数度其他全为偶数度(感觉第二个不用)
再就是dfs去扫。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 const int maxn=205; 7 8 int G[maxn][maxn],vis[maxn]; 9 10 int n,r; 11 12 void dfs(int x) 13 { 14 for(int i=0;i<n;i++) 15 { 16 if(G[x][i]) 17 { 18 G[x][i]--; 19 G[i][x]--; 20 vis[i]--; 21 vis[x]--; 22 dfs(i); 23 } 24 } 25 } 26 27 int main() 28 { 29 while(~scanf("%d %d",&n,&r)) 30 { 31 int s,e; 32 memset(G,0,sizeof(G)); 33 memset(vis,0,sizeof(vis)); 34 35 for(int i=0;i<r;i++) 36 { 37 scanf("%d %d",&s,&e); 38 G[s][e]++; 39 G[e][s]++; 40 vis[e]++; 41 vis[s]++; 42 } 43 44 int cnt=0; 45 for(int i=0;i<n;i++) 46 if(vis[i] & 1) 47 { 48 cnt++; 49 break; 50 } 51 52 if(cnt || r<2) printf("Not Possible\n"); 53 else 54 { 55 int flag=true; 56 dfs(0); 57 58 for(int i=0;i<n;i++) 59 if(vis[i]) 60 flag=false; 61 if(flag) printf("Possible\n"); 62 else 63 printf("Not Possible\n"); 64 } 65 } 66 return 0; 67 }
uva,10926
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 6 using namespace std; 7 8 const int maxn=105; 9 int map[maxn][maxn]; //一开始用的queue但是每次扫一次就清空了, 10 //wa了几次 11 int cnt[maxn]; 12 int vis[maxn]; 13 int ans; 14 int n; 15 16 void dfs(int t) 17 { 18 for(int i=1;i<=n;i++) 19 { 20 if(map[t][i] && !vis[i]) 21 { 22 ans++; 23 vis[i]=1; 24 dfs(i); 25 } 26 } 27 } 28 29 int main() 30 { 31 while(scanf("%d",&n),n) 32 { 33 34 int t,b; 35 memset(map,0,sizeof(map)); 36 for(int i=1;i<=n;i++) 37 { 38 scanf("%d",&t); 39 for(int j=0;j<t;j++) 40 { 41 scanf("%d",&b); 42 map[i][b]=1; 43 } 44 } 45 memset(cnt,0,sizeof(cnt)); 46 for(int i=1;i<=n;i++) 47 { 48 memset(vis,0,sizeof(vis)); 49 ans=0; 50 dfs(i); 51 cnt[i]+=ans; 52 } 53 int max=0; 54 int index=0; 55 for(int i=1;i<=n;i++) 56 { 57 if(max<cnt[i]) 58 { 59 max=cnt[i]; 60 index=i; 61 } 62 } 63 printf("%d\n",index); 64 } 65 return 0; 66 }