CRP week8周报

B3647 【模板】Floyd

1.思路:这是一道用floyd解决的模板题

2.代码:

#include <bits/stdc++.h>
using namespace std;
int f[105][105];
int main()
{
	int n,m;
	cin>>n>>m;
	memset(f,0x3f3f3f3f,sizeof(f));
	for(int i=1;i<=m;i=i+1)
	{
		int u,v,w;
		cin>>u>>v>>w;
		f[u][v]=w;
		f[v][u]=w;
	}
	for(int i=1;i<=n;i=i+1)
	{
		f[i][i]=0;
	}
	for(int k=1;k<=n;k=k+1)
	{
		for(int v=1;v<=n;v=v+1)
		{
			for(int w=1;w<=n;w++)
			{
				if(f[v][w]>f[v][k]+f[k][w])
				{
					f[v][w]=f[v][k]+f[k][w];
				}
			}
		}
	}
	for(int i=1;i<=n;i=i+1)
	{
		for(int j=1;j<=n;j=j+1)
		{
			if(j==1)
			{
				cout<<f[i][j];
			}
			else
			{
				cout<<" "<<f[i][j];
			}
		}
		cout<<endl;
	}
}

P4779 【模板】单源最短路径(标准版)

1.思路:这是用迪杰斯特拉算法做单源最短路径的标准化模板,里面用到了链式前向星的空间优化以及用优先队列的堆优化,降低了时间复杂度。

2.代码:

#include <bits/stdc++.h>
using namespace std;
int cnt;
int head[1000005];
int m,n,s;
int ans[1000005];
int vis[1000005];
struct edge
{
	int to,wei,nextt;
}edge[1000005];
struct priority
{
	int ans;
	int id;
	bool operator <(const priority &x)const
	{
		return x.ans<ans;
	}
};
void addedge(int x,int y,int z)
{
	edge[++cnt].to=y;
	edge[cnt].wei=z;
	edge[cnt].nextt=head[x];
	head[x]=cnt;
}
priority_queue <priority> q;
int main()
{
	cin>>m>>n>>s;
	for(int i=1;i<=n;i=i+1)
	{
		ans[i]=0x3f3f3f3f;
	}
	ans[s]=0;
	for(int i=1;i<=n;i=i+1)
	{
		int a,b,c;
		cin>>a>>b>>c;
		addedge(a,b,c);
	}
	int u;
	q.push((priority){0,s});
	while(!q.empty())
	{
		priority temp=q.top();
		q.pop();
		u=temp.id;
		if(!vis[u])
		{
			vis[u]=1;
			for(int i=head[u];i;i=edge[i].nextt)
			{
				int v=edge[i].to;
				if(ans[v]>ans[u]+edge[i].wei)
				{
					ans[v]=ans[u]+edge[i].wei;
					if(!vis[v])
					{
						q.push((priority){ans[v],v});
					}
				}
			}
		}
	}
	for(int i=1;i<=m;i=i+1)
	{
		cout<<ans[i]<<" ";
	}
}

 P2661 [NOIP2015 提高组] 信息传递

1.思路:其实我自己没啥思路,看了题解后发现许多人都用并查集来求最小环,当找父节点找了一圈后发现正好等于自己,这就说明构成了一个环,并且查找深度就是环的大小。

2.代码:

#include <bits/stdc++.h>
using namespace std;
int fa[200005];
int deep;
int ans=0x3f3f3f3f;
int f[200005];
int find(int x,int &deep)
{
	deep++;
	if(fa[x]==x)return x;
	else
	{
		return find(fa[x],deep);
	}
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i=i+1)
	{
		fa[i]=i;
	}

	for(int i=1;i<=n;i=i+1)
	{
		deep=0;
		int f;
		cin>>f;
		int h=find(f,deep);
		if(h==i)
		{
			ans=min(ans,deep);
		}
		else
		{
			fa[i]=f;
		}
	}
	cout<<ans;
}

 P1144 最短路计数

1.思路:求最短路用迪杰斯特拉算法的模板,但是我们需要在模板的基础上,添加求最短路径条数的代码。

2.代码:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int head[2000005];
int cnt;
long long ans[1000005];
int js[1000005];
bool vis[1000005];
int mod=100003;
struct bian
{
	int to,wei,nextt;
}edge[2000005];
struct priority
{
	int ans;
	int id;
	bool operator <(const priority &x)const
	{
		return x.ans<ans;
	}
};
void addedge(int x,int y,int z)
{
	edge[++cnt].to=y;
	edge[cnt].wei=z;
	edge[cnt].nextt=head[x];
	head[x]=cnt;
}
priority_queue <priority> q;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i=i+1)
	{
		ans[i]=0x3f3f3f3f;
	}
	for(int i=1;i<=m;i=i+1)
	{
		int a,b;
		int c=1;
		cin>>a>>b;
		addedge(a,b,c);
		addedge(b,a,c);
	}
	ans[1]=0;
	js[1]=1;
	int u;
	q.push((priority){0,1});
	while(!q.empty())
	{
		priority temp=q.top();
		q.pop();
		u=temp.id;
		int d=temp.ans;
		if(!vis[u])
		{
			vis[u]=1;
			for(int i=head[u];i;i=edge[i].nextt)
			{
				int v=edge[i].to;
				if(d+edge[i].wei==ans[v])
				{
					js[v]=(js[u]+js[v])%mod;
				}
				if(ans[v]>ans[u]+edge[i].wei)
				{
					ans[v]=ans[u]+edge[i].wei;
					js[v]=js[u];
					if(!vis[v])
					{
						q.push((priority){ans[v],v});
					}
				}
			}
		}
	}
	for(int i=1;i<=n;i=i+1)
	{
		cout<<js[i]<<endl;
	}
}

 P8794 [蓝桥杯 2022 国 A] 环境治理

1.思路:题目中求经过的天数的最小值,并且可以发现天数是按递增的方式排序的,可以用二分进行查找,另外可以用floyd算法求出每两点之间的最短距离,最后叠加求出灰尘度。

2.代码:

#include <bits/stdc++.h>
using namespace std;
int d[105][105];
int li[105][105];
int n;
int q;
int check(int mid)          
{
    int tmp[105][105];
	int i,j,k;
	for (i =0; i<n; i++)
		for (j =0; j<n; j++)
			tmp[i][j]=d[i][j];
	for (i =0; i<n; i++)
	{
		int v= mid/n+(mid%n>=i+1?1:0);
		for (j =0 ; j<n; j++)
		{
		    tmp[i][j]-=v;
		    if (tmp[i][j]<li[i][j]) tmp[i][j]=li[i][j];
		    tmp[j][i]-=v;
		    if (tmp[j][i]<li[j][i]) tmp[j][i]=li[j][i];
		}
	}
	for (k =0 ; k<n; k++)        
		for (i =0 ; i<n; i++)
			for (j =0 ; j<n; j++)
				tmp[i][j]=min(tmp[i][j],tmp[i][k]+tmp[k][j]);
	int res =0 ;
	for (i =0; i<n; i++)     // 计算治理后的P指标值
		for (j =0; j<n; j++)
			res+=tmp[i][j];
	if(res<=q)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
int find()
{
	int  l=0;
	int r=100000*n;
	while (l+1<r)
	{
		int mid=(l+r)/2;
		if (check(mid))
		{
			r= mid;
		}
		else
			l=mid;
	}	
	return r;
}
int main()
{
	cin>>n>>q;
	int i,j;
	for (i =0; i<n; i++)
		for (j =0 ; j<n; j++)
			scanf("%d",&d[i][j]);
	for (i =0; i<n; i++)
		for (j =0 ; j<n; j++)
			scanf("%d",&li[i][j]);
	int h=find();
	if(h==100000*n)
	{
		cout<<-1;
	}
	else
	{
		cout<<h;
	}
}

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值