NEUQ-ACM预备队week9

NEUQ-ACM预备队week9

1. 查找文献(P5318)
#include<bits/stdc++.h>
using namespace std;
inline int read()//二进制优化的快读 
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
	{
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
	{
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
int n,m;
bool b[100005];//定义b数组防止重复输出 
vector<int > a[100005];
void dfs(int x,int r)//x表示所在点,r表示剩余未遍历的点 
{
	b[x]=true;//记录某点已经输出过 
	if(!r)//如果每个点都遍历过终止递归 
	{
		cout<<x<<' ';
		return ;
	}
	cout<<x<<' ';
	for(int i=0;i<a[x].size();i++)
	if(!b[a[x][i]]) dfs(a[x][i],r-1);//查找从x可以到的点,并遍历 
}
void bfs()
{
	queue<int> q;
	q.push(1);b[1]=true;//把1点放入队列中,并标记1点已经遍历过 
	while(!q.empty())
	{
		int s=q.front(); q.pop();//拿出队列首的那个点 
		cout<<s<<' ';
		for(int i=0;i<a[s].size();i++) if(b[a[s][i]]==false) q.push(a[s][i]),b[a[s][i]]=true;//把点s所能到达的点遍历,为防止TLE和重复输出,记录已遍历过的点 
	}
}
int main()
{
	n=read();
	m=read();
	for(int i=1;i<=m;i++) 
	{
		int x,y;
		x=read();
		y=read();
		a[x].push_back(y);//建图 表示x可以到y 
	}
	for(int i=1;i<=n;i++)//把每条路所通向的点从小到大排列(题目中有要求) 
	sort(a[i].begin(),a[i].end());//快排  
	dfs(1,n);//进行深搜 从1点开始,进行n次 
	cout<<endl;
	for(int i=1;i<=n;i++) b[i]=false;//初始化 
	bfs();//进行广搜 
	return 0;
}
2. floyd(U80592)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 505,INF = 1e9,mod = 998244354;
int n,m;
int f[N][N];
int ans[N];
int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m;
    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] = INF;
        }
    }
    for(int i = 1;i <= m; i++)
    {
        int u,v,w;
        cin >> u >> v >> w;
        f[u][v] = min(f[u][v],w);
        f[v][u] = min(f[v][u],w);
    }
    for (int k = 1; k <= n; k++) {
        for (int x = 1; x <= n; x++) {
            for (int y = 1; y <= n; y++) {
                f[x][y] = min(f[x][y], f[x][k] + f[k][y]);
            }
        }
    }
    for(int i = 1;i <= n; i++){
        for(int j = 1;j <= n; j++){
            if(f[i][j] != INF) ans[i] = (ans[i] + f[i][j]) % mod;
        }
    }
    for(int i = 1;i <= n; i++){
        cout << ans[i] << endl;
    }
    return 0;
}
3. 单源最短路径(P4779)
#include<bits/stdc++.h>
using namespace std;
struct edge//链式前向星式存图
{
	int v;
	int to;
	int next;
}e[500005];
//链式前向星
int head[500005],v[500005],cnt;//v数组是迪杰斯特拉中用于存以s为起点,到每个点的最短路径
int vis[500005];//迪杰斯特拉算法,标记点是否走过
int n, m,s;
void add_edge(int u, int v, int l)//链式前向星的加边
{
	cnt++;
	e[cnt].to = v;
	e[cnt].next = head[u];
	e[cnt].v = l;
	head[u] = cnt;
}

struct node//dijkstra算法中的点,需要存储这个点的坐标和这个点的值
{
	int v;//点的值
	int pos;//位置
	bool operator <(const node& x)const//前问谈到的内置比较函数,否则无法存入优先队列中
	{
		return x.v < v;
	}
};
priority_queue<node> q;//堆优化

void dijkstra()
{
	v[s] = 0;//起点设为0
	node tmp = { 0,s };
	q.push(tmp);//起点的权值为0,位置于起点
	{
		while (!q.empty())
		{
			tmp = q.top();
			q.pop();
			int x = tmp.pos, t = tmp.v;
			if (vis[x] == 1) continue;//这个点走过了 ,它的最短路已经被确定
			vis[x] = 1;
			for (int i = head[x]; i != -1; i = e[i].next)//链式前向星的遍历
			{
				int y = e[i].to;
				if (v[y] > v[x] + e[i].v)//y点的值比x点值加边权大,更新答案
				{
					v[y] = v[x] + e[i].v;
					if (vis[y] == 0)//推入y点,以找到它所能到达的所有点
					{
						tmp.pos = y;
						tmp.v = v[y];
						q.push(tmp);
					}
				}
			}
		}
	}
}
int main()
{
	memset(head, -1, sizeof(head));//初始化head数组
	cin >> n >> m >> s;
	for (int i = 1; i <= n; i++) v[i] = 0x7fffffff;//dijkstra的初始化,每个点的v值初始化为无穷
	for (int i = 0; i < m; i++)
	{
		int u, v, d;
		cin >> u >> v >> d;//链式前向星的加边
		add_edge(u, v, d);

	}
	dijkstra();
	for (int i = 1; i <= n; i++) cout << v[i]<<" ";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值