图论相关题

  • 查找文献

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,m;
    const int maxn=2e5;
    int vis[maxn]={0};
    vector<int>e[maxn];//存图
    
    vector<int>res;//存储答案
    //dfs:x:表示数此时的值
    void dfs(int x)
    {
    	vis[x]=1;
    	res.push_back(x);
    	if(x>n||e[x].empty()) return ;
    	sort(e[x].begin(),e[x].end());
    	for(int i=0;i<e[x].size();i++)
    	{
    		int nx=e[x][i];
    		if(vis[nx]==0)
    		{
    			dfs(nx);
    			//无需回溯
    		}
    	}
    }
    //bfs
    void bfs(int i)
    {
    	queue<int>q;
    		q.push(i);
    		res.push_back(i);
    		vis[i]=1;
    		while(!q.empty())
    		{
    			int nx=q.front();
    			q.pop();
    			sort(e[nx].begin(),e[nx].end());
    			for(int j=0;j<e[nx].size();j++)
    			{
    				int ny=e[nx][j];
    				if(vis[ny]==0)
    				{
    					res.push_back(ny);
    					q.push(ny);
    					vis[ny]=1;
    				}
    			}
    		}
    }
    int main()
    {
    	cin>>n>>m;
    	//存图
    	for(int i=1;i<=m;i++)
    	{
    		int x,y;
    		cin>>x>>y;
    		e[x].push_back(y);
    	}
    	int m=1;
    	//判断是否会出现有文件的参考文件为1
    	for(int i=1;i<=n;i++)
    	{
    		if(e[i].size()==1&&e[i][0]==1)
    		m=i;
    	}
    	dfs(1);
    	//如果有 是否能通过1为起点遍历树
    	if(m!=1&&sizeof(res)<n)
    	{
    		res.clear();
    	    memset(vis,0,sizeof(vis));
    		dfs(m);
    	}
    	fo j=0;j<res.size();j++)
    	cout<<res[j]<<" ";
    	res.clear();
    	memset(vis,0,sizeof(vis));
    
    	cout<<endl;
    	memset(vis,0,sizeof(vis));
    	res.clear();
    	//同样进行判断
    	bfs(1);
    	if(m!=1&&sizeof(res)<n)
    	{
    		res.clear();
    	    memset(vis,0,sizeof(vis));
    	    bfs(m);
    	}
    	for(int j=0;j<res.size();j++)
    	cout<<res[j]<<" ";
    	return 0;
    }
    
    • floyd

      #include<bits/stdc++.h>
      using namespace std;
      struct edge{
      	int to;
      	long long w;
      };
      long long f[510][510];
      int main()
      {
      	int n,m;
      	cin>>n>>m;
      	memset(f,0x3f3f3f3f,sizeof(f));
      	for(int i=1;i<=n;i++)
      	{
      		for(int j=1;j<=n;j++)
      		{
      			if(i==j)
      			f[i][j]=0;
      			else
      			f[i][j]=0x3f3f3f3f3f;//设置为无穷大
      		}
      	}
      	for(int i=1;i<=m;i++)
      	{
      		int u,v;
      		long long w;
      		cin>>u>>v>>w;
      		f[u][v]=min(w,f[u][v]);//存图是考虑到重边的情况【存最短的边】
      		f[v][u]=f[u][v];
      	}
      	//floyd
      	for(int k=1;k<=n;k++)
         {
      	for(int i=1;i<=n;i++)
      	{
      		for(int j=1;j<=n;j++)
      		{
      			f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
      		}
      	}
          }
          //结果输出
          int sum=0;
          for(int i=1;i<=n;i++)
          {
      		sum=0;
      		for(int j=1;j<=n;j++)
          	{
      			if(f[i][j]!=0x3f3f3f3f3f)
      			sum=(sum+f[i][j])%998244354;
      		}
      		cout<<sum<<endl;
      	}
      	return 0;
      }
      
  • 单源最短路径【用优先队列储存】

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5*1e5+5;
    long long  head[maxn];
    int tot=0;
    struct edge
    {
    	int v,w,next;
    }e[maxn];
    //在队列中存入距离的最短值&第几个
    struct node{
    	int dis,pos;
    	//自定义符号
    	bool operator<(const node&x) const
    	{
    		return x.dis<dis;
    	}
    };
    //存图
    void add(int u, int v, int w)
    {
    	e[++tot]={v,w,head[u]},head[u]=tot;
    }
    int dis[maxn];
    bool vis[maxn];
    std::priority_queue<node>q;
    int main()
    {
    	int n,m,s;
    	cin>>n>>m>>s;
    	//初始化
    	for(int i=1;i<=n;++i) dis[i]=0x7fffffff;
    	//存图
    	for(register int i=0;i<m;i++)
    	{
    		register int u,v,w;
    		cin>>u>>v>>w;
    		add(u,v,w);
    	}
    	//存入起点
      dis[s]=0;
      q.push((node){0,s});
      
      while(!q.empty())
      {
      	node tmp=q.top();
      	q.pop();
      	int x=tmp.pos;
      	int d=tmp.dis;
      	if(vis[x]) continue;//如果该点已经在最短集里面
      	vis[x]=1;
      	for(int i=head[x];i;i=e[i].next)
      	{
      		int y=e[i].v;
      		if(dis[y]>dis[x]+e[i].w)
      		{
      			dis[y]=dis[x]+e[i].w;更新路径长度
      			if(!vis[y])
      			{
      				q.push((node){dis[y],y});//存入新点
    			  }
    		  }
    	  }
      }
      for(int i=1;i<=n;++i)
      cout<<dis[i]<<" ";
      return 0;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值