洛谷——《图》

本文介绍了如何使用C++编程语言实现广度优先搜索(BFS)、深度优先搜索(DFS)以及拓扑排序算法,包括针对有向无环图(DAG)的处理,适用于解决图论中的基本问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<set>
#include<map>
#include<algorithm>
#include<cmath>
using namespace std;



//广度优先遍历

// bool visted[MAx];
// void BFSTraverse(Graph G)
// {
//     for(int i =0;i<=G.vexnum;i++)
//     visited[i] = false;
//     InitQueue(Q);
//     for(int i =1;i<=G.vexnum;i++)
//     {
//         if(!visited[i])
//         {
//             BFS(G,i);
//         }
//     }
// }
// void BFS(Graph G,int v)//从顶点v出发
// {
//     visit(v);
//     visited[v] = true;
//     Enqueue(Q,v);
//     while(!isEmpty(Q))
//     {
//         DeQueue(Q,v);
//         for(w = FirstNeighbor(G,v);w>=0.w = NextNeighbor(G,v,w))
//         {
//             if(!visited[w])
//             {
//                 visit(w);
//                 visited[w] = true;
//                 EnQueue(Q,w);
//             }
//         }
//     }
// }


//深度优先遍历


// bool visted[MAx];

// void PreOrder(TreeNode *R)
// {
//     if(R!=NULL)
//     {
//         visit(R);
//         while()//子树T
//         {
//             PreOrder(T);
//         }
//     }
// }


// void DFS(Graph G,int v)//从顶点v出发
// {
//     visit(v);
//     visited[v] = true;
//     for(w = FirstNeighbor(G,v);w>=0.w = NextNeighbor(G,v,w))
//     {
//         if(!visited[w])
//         {
//            DFS(G,w);
//         }
//     }
// }

// void DFSTraverse(Graph G)
// {
//     for(int i =0;i<=G.vexnum;i++)
//         visited[i] = false;
//     for(int i =1;i<=G.vexnum;i++)
//     {
//         if(!visited[i])
//         {
//             BDS(G,i);
//         }
//     }
// }


//DAG(有向无环图)

//拓扑排序(AOV网,DAG)
//  找到入度为0的顶点
// 从网中删除该顶点和以它为起点的有向边
// 重复1,2直到aov网为空
// 可能有多个拓扑排序

// #define MaxVertexNum 100
// struct ArcNode//边表节点
// {
//     int adjvex;//该弧指向顶点位置
//     ArcNode *nextarc; 
// };

// typedef struct VNode
// {
//     int data;
//     ArcNode *firstarc;//指向第一条边的弧指针
// }VNode,AdjList[MaxVertexNum];

// struct Graph
// {
//     AdjList vertice;
//     int vexnum,arcnum;//顶点数和边数
// };

// bool TopologicalSort(Graph G)
// {
//     InitStack(S);//初始化栈
//     for(int i =0;i<G.vexnum;i++)
//     {
//         if(indegree[i]==0)
//         {
//             S.push(i);//先放入入度为0的元素
//         }
//     }
//     int count =0;
//     while(!S.Empty())
//     {
//         int i =S.pop();
//         print[count++] = i;//存入拓扑排序
//         for(p = G.vertice[i].firstarc;p;p=p->nextarc)
//         {
//             v=p->adjvex;
//             if(!(--indegree[v]))
//                 S.push(v);
//         }
//     }
//     if(count<G.vexnum)return false;
//     else return true;
// }

//p1113

// #define MAX 10010
// int len[MAX],vis[MAX];
// vector<int>arr[MAX];
// int n,x,y,ans;

// int dfs(int a)
// {
//     if(vis[a])return vis[a];
//     for(int i=0;i<arr[a].size();i++)
//     {
//         int item = arr[a][i];
//         vis[a] = max(vis[a],dfs(item));//找到最大长度
//     }
//     vis[a]+=len[a];
//     return vis[a];
// }
// int main()
// {
//     cin>>n;
//     for(int i =1;i<=n;i++)
//     {
//         cin>>x>>len[i];
//         cin>>y;
//         while(y)
//         {
//             arr[y].push_back(x);
//             cin>>y;
//         }
//     }
//     for(int i = 1;i<=n;i++)
//         ans = max(ans,dfs(i));
//     cout<<ans;
// }

// #define MAX 5005
// #define MAXM 500005
// #define MOD 80112002
// int n,m,ans;
// int out[MAXM],in[MAXM],f[MAXM];//出度,入度和链数
// vector<int>arr[MAX];
// queue<int>q;
// int main()
// {
//     cin>>n>>m;
//     for(int i =1;i<=m;i++)
//     {
//         int x,y;
//         cin>>x>>y;
//         out[x]++;
//         in[y]++;
//         arr[x].push_back(y);
//     }
//     for(int i =1;i<=n;i++)
//     {
//         if(in[i]==0)
//         {
//             q.push(i);//入队
//             f[i] = 1;
//         }
//     }
//     while(!q.empty())
//     {
//         int item = q.front();q.pop();//弹出队首
//         for(int i =0;i<arr[item].size();i++)
//         {          
//             int y = arr[item][i];
//             f[y] =(f[y]+f[item])%MOD;
//             if(--in[y]==0)
//             {
  
//                 q.push(y);
//             }
//         }
//     }

//     for(int i=1;i<=n;i++)
//     {
//         if(out[i]==0)ans = (ans+f[i])%MOD;
//     }
//     cout<<ans;
// }


// p1807
// 1.拓扑排序
// int n,m,u,v,w,ans;
// int in[1505];//入度
// vector<int> t[1505];//存边
// vector<int> d[1505];//存权
// queue<int> q;//建立队列
// int s[1505];//存最长路
// main()
// {
//     cin>>n>>m;
//     for(int i =0;i<m;i++)
//     {
//         cin>>u>>v>>w;
//         in[v]++;//入度
//         t[u].push_back(v);
//         d[u].push_back(w);
//     }//初始化

//     for(int i =2;i<=n;i++)
//     {
//         s[i] = -1e9;
//         if(in[i]==0)q.push(i);//入队
//     }
     
//     while(!q.empty())
//     {
//         int item = q.front();q.pop();
//         for(int i=0;i<t[item].size();i++)
//         {
//             int j = t[item][i];
//             if(!--in[j])q.push(j);
//         }
        
//     }
//     q.push(1);
//     while(!q.empty())
//     {
//         int item = q.front();q.pop();//队首
//         for(int i=0;i<t[item].size();i++)
//         {
//             int j = t[item][i];//边
//             s[j] = max(s[j],s[item]+d[item][i]);//最大更新权
//             if(--in[j]==0)q.push(j);//加入边
//         }

//     }
//     if(s[n]==-1e9)cout<<-1;
//     else cout<<s[n];
// }


// p1127
// 1.存储用地图数组,存字符串和对应的最后字母
// 2.从a-z遍历,每次找到最后字母最小的,放入链中标记,找到最后字母位置,重复
// (36分,后面有时间再改)
// int n;
// string ans;
// vector<map<string,char>>arr(200);
// map<string,bool> M;//标记
// map<string,int> T;//计次
// int S;//记录大小
// bool flag;
// void find(char ch)
// {
//     int i= arr[ch].size();
//     if(S==0)return;//出口
//     if(!i)
//     {
//         flag = 1;
//         return;
//     }
//     string s;
//     char m = 'z';
//     auto pos = arr[ch].begin();
//     if(arr[ch].size())
//     {
//         for(auto it = arr[ch].begin();it!= arr[ch].end();it++)
//         {
            
//             if(it->second<m)//找到最小字符
//             {
//                 m = it->second;
//                 pos = it;//记录最小位置
//             }
//         }
//     }
//     while(T[pos->first]--)ans+=pos->first;//加入
//     ans+='.';
//     S--;
//     arr[ch].erase(pos->first);//删除
//     find(m);

// }
// int main()
// {
//     cin>>n;
//     for(int i =0;i<n;i++)
//     {
//         string item;
//         char last,first;
//         cin>>item;
//         last = item[item.length()-1];
//         first = item[0];
//         //获取首尾元素
//         if(arr[first].find(item)==arr[first].end())
//         {
//             arr[first].insert({item,last});//无重复加入
//             S++;
//         }
//         T[item]++;

//         //初始化

//     }
//     //变量
//     for(int i = 'a';i<='z';i++)
//         if(arr[i].size())
//         {
//             find(i);
//             break;
//         }
//     if(flag)cout<<"***";
//     else cout<<ans.substr(0,ans.length()-1);
// }






//p2853
// 1.建立图
// 2.农场数组:奶牛到达个数
// 3.dfs
// 4.遍历数组,统计奶牛数为n的农场

// int k,n,m,pas,ans;
// vector<int>arr[1005];
// int pasture[1005],t[1005],fin[1005];//奶牛个数,奶牛初始位置,通过位置

// void dfs(int x)
// {
//     if(fin[x])return;
//     pasture[x]++;
//     fin[x] = 1;
//     for(int i =0;i<arr[x].size();i++)
//     {
//         int item = arr[x][i];
//         if(!fin[item])dfs(item);
//     }
// }
// int main()
// {
//     cin>>k>>n>>m;
//     for(int i =1;i<=k;i++)
//     {
//         cin>>pas;
//         t[i] = pas;//奶牛初始位置
//     }
//     for(int i =1;i<=m;i++)
//     {
//         int x,y;
//         cin>>x>>y;
//         arr[x].push_back(y);
//     }//初始化
//     for(int i = 1;i<=k;i++)
//     {
//         memset(fin,0,sizeof(fin));
//         dfs(t[i]);
//     }
//     for(int i =1;i<=n;i++)
//     {
//         if(pasture[i]==k)ans++;
//     }
//     cout<<ans;
// }


//p1363
// 1.题意表示从上到下有路径,且上下有重合,左右同理
// 2.通过dfs找到所以s能到达的点,用数组标记
// 3.判断左右和上下重合
// (抄都抄不会,最后一个点不知道怎么弄)
// int n,m,x,y,ans;
// bool flag[1501][1501];//dfs标记
// int arr[1501][1501][3];//存储
// int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};//四个方向
// void dfs(int a,int b,int posa,int posb)
// {
//     if(arr[posa][posb][2]==1&&(arr[posa][posb][0]!=a||arr[posa][posb][1]!=b))
//     {
//         ans = 1;
//         return;//存在回路但不重复
//     }
//     if(arr[posa][posb][2]==1&&arr[posa][posb][0]==a&&arr[posa][posb][1]==b)return;
//     arr[posa][posb][2]=1;arr[posa][posb][0]=a;arr[posa][posb][1]=b;
//     register int ux,uy;
//     for(int i =0;i<4;i++)
//     {
//         ux = posa+dir[i][0],uy = posb+dir[i][1];//四个可能位置
//         ux = (n+ux)%n;uy = (m+uy)%m;
//         if(flag[ux][uy])dfs(a+dir[i][0],b+dir[i][1],ux,uy);//
//     }
// }

// int main()
// {
//     ios::sync_with_stdio(false);
//     register char ch;
//     while(cin>>n>>m)
//     {
//         memset(flag,0,sizeof(flag));
//         memset(arr,0,sizeof(arr));
//         for(int i =0;i<n;i++)
//         {
//             for(int j=0;j<m;j++)
//             {
//                 cin>>ch;
//                 if(ch=='.')flag[i][j] = 1;
//                 else if(ch=='S')
//                 {
//                     x = i;y = j;//记录S坐标
//                     flag[i][j] =1;
//                 }
//             }
//         }//初始化
//         ans =0;
//         dfs(x,y,x,y);
//         if(ans)cout<<"Yes"<<endl;
//         else cout<<"No"<<endl;
//     }
// }

//p1347
// 1.顺序确定:哈密顿通路,也就是拓扑n层
// 2.矛盾判断:存在回路,拓扑没有遍历所有点
// 3.顺序输出:拓扑排序
//真难搞
// int n,m,Size,k;
// char a,b,c;
// vector<int>arr[30];
// set<int> ds;
// int in[30],h,flag[30],sum,t[30];//入度数和层,标记
// queue<int>q;

// string tuopu()
// {
//     string ans;
//     for(int i =0;i<26;i++)
//     {
//         in[i] = t[i];
//         if(!in[i]&&ds.find(i)!=ds.end())
//         {
//             q.push(i);//入度初始化
//             flag[i] = 1;//标记
//             sum++;
//         }
//     }
//     while(!q.empty())
//     {
//         h++;//层数加一
//         for(int i =0;i<q.size();i++)
//         {
//             int item = q.front();q.pop();
//             ans +='A'+item;
//             for(int i=0;i<arr[item].size();i++)
//             {
//                 int j = arr[item][i];
//                 if(!--in[j]&&!flag[j])
//                 {
//                     q.push(j);
//                     flag[j] = 1;
//                     sum++;
//                 }
//             }
//         }
       
//     }
//     return ans;
// }

// void final()
// {
//     h =0;
//     sum =0;
//     memset(flag,0,sizeof(flag));
//     string ans = tuopu();
//     if(h==n)
//     {
//         cout<<"Sorted sequence determined after "<<k<<" relations: "<<ans<<'.';
//         exit(0);
//     }

//     if(sum!=Size) 
//     {
//         cout<<"Inconsistency found after "<<k<<" relations.";
//         exit(0);
//     }
// }
// int main()
// {
//     cin>>n>>m;
//     for(k =1;k<=m;k++)
//     {
//         cin>>a>>b>>c;
//         arr[a-'A'].push_back(c-'A');
//         t[c-'A']++;//入度
//         ds.insert(a-'A');
//         ds.insert(c-'A');
//         Size = ds.size();//个数
//         final();
//     }//初始化
//     cout<<"Sorted sequence cannot be determined.";

   
// }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值