0
点赞
收藏
分享

微信扫一扫

2/3 熬夜刷题~~~

慎壹 2022-02-04 阅读 40

https://www.luogu.com.cn/problem/P3906
P3906 Geodetic集合
bfs深搜的灵活应用,算我的薄弱点。

#include <bits/stdc++.h>

using namespace std;
const int inf=0x3f3f3f3f;
int n,m,pre[50][50],dist[50],mp[50][50],k,num[50];
bool vis[50];
void bfs(int s,int t)
{
    memset(num,0,sizeof(num));     //记录前驱结点个数
    memset(dist,inf,sizeof(dist)); //dist数组都初始化为极大值,吴话可说
    dist[s]=0;                     //起始结点距离为0
    queue<int>q;q.push(s);
    while(!q.empty())
    {
        s=q.front();q.pop();
        for(int i=1;i<=n;i++)
        {
            if(mp[s][i])        //若存在边
            {
                if(dist[i]>dist[s]+1)  //简单dp思想
                {
                    dist[i]=dist[s]+1;
                    pre[i][++num[i]]=s;  //以i为节点的前驱节点都标记为s(上一个结点),num[i]表示几个
                    q.push(i);
                }
                else if(dist[i]==dist[s]+1)
                    pre[i][++num[i]]=s;
            }
        }
    }
    memset(vis,0,sizeof(vis));q.push(t);vis[t]=1; //从目标结点t倒着搜上去
    while(!q.empty())
    {
        s=q.front();q.pop();
        for(int i=num[s];i>=1;i--)  //以s为结点的前驱节点,标记为1
        {
            if(!vis[pre[s][i]])
                vis[pre[s][i]]=1;
                q.push(pre[s][i]);
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(vis[i])
            printf("%d ",i);
    }
    cout<<endl;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        mp[x][y]=1;mp[y][x]=1;
    }
    scanf("%d",&k);
    for(int i=1;i<=k;i++)
    {
        int u,v;scanf("%d%d",&u,&v);
        bfs(u,v);
    }
    return 0;
}

P3905 道路重建
https://www.luogu.com.cn/problem/P3905
只对被破坏的交通赋值,完好的交通赋值为0,求从a到b的最短路径即可。

#include <bits/stdc++.h>

using namespace std;
const int maxn=200005;
const int inf=0x3f3f3f3f;
struct egde
{
    int to,dis,nxt;
}e[maxn];
int n,m,d,a,b,s,head[maxn],dist[maxn],cnt,ag[5005][5005];
bool vis[maxn];
void add_edge(int from,int to,int dis)
{
    e[++cnt].to=to;
    e[cnt].dis=dis;
    e[cnt].nxt=head[from];
    head[from]=cnt;
}
struct node
{
    int pos,dis;
    bool operator <(const node &x)const
    {
        return x.dis<dis;
    }
};
void dijkstra()
{
    s=a;
    dist[s]=0;
    priority_queue<node>q;q.push(node{s,0});
    while(!q.empty())
    {
        node cur=q.top();q.pop();
        int now=cur.pos;
        if(vis[now]) continue;
        vis[now]=1;
        for(int i=head[now];i!=-1;i=e[i].nxt)
        {
            int j=e[i].to;
            if(dist[j]>dist[now]+e[i].dis)
            {
                dist[j]=dist[now]+e[i].dis;
                q.push(node{j,dist[j]});
            }
        }
    }

}
int main()
{
    scanf("%d%d",&n,&m);
    head[0]=-1;
    for(int i=1;i<=n;i++)
        head[i]=-1,dist[i]=inf;
    for(int i=1;i<=m;i++)
    {
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        ag[u][v]=w,ag[v][u]=w;
        add_edge(u,v,0),add_edge(v,u,0);
    }
    scanf("%d",&d);
    for(int g=1;g<=d;g++)
    {
        int x,y;scanf("%d%d",&x,&y);
        for(int i=head[x];i!=-1;i=e[i].nxt)
        {
            if(e[i].to==y) e[i].dis=ag[x][y];
        }
        for(int i=head[y];i!=-1;i=e[i].nxt)
        {
            if(e[i].to==x) e[i].dis=ag[y][x];
        }
    }
    scanf("%d%d",&a,&b);
    dijkstra();
    printf("%d\n",dist[b]);
    return 0;
}

https://www.luogu.com.cn/problem/P6175
Floyd算法:复杂度高,但能算出任意两点的最短路径。
(此段注解使用别人的解释,非常有道理,对于处理最小环的问题)
我们知道,
在Floyd算法枚举 k的时候,已经得到了前 k-1 个点的最短路径,这 k-1 个点不包括点 k,并且他们的最短路径中也不包括 k 点。
那么我们便可以从这前 k-1 个点中选出两个点 i , j 来
因为 / i-j / 已经是 ( i , j ) 间的最短路径,且这个路径不包含 k 点
注解:这里 / i-j / 这样表达只是为了直观,实际中 ( i , j ) 间的最短路很可能不仅仅只有 / i-j / ,还有可能会有其他点,但是这条路径一定是 ( i , j ) 间的最短路
所以连接 / i-j-k-i / ,我们就得到了一个经过 i , j , k 的最小环
最后每次更新 ans 的最小值即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn=200;
int n,m;
int dis[maxn][maxn];
int mp[maxn][maxn];
signed main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(i!=j)dis[i][j]=mp[i][j]=inf;
	for(int i=1;i<=m;i++)
    {
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        dis[u][v]=min(dis[u][v],w);
        dis[v][u]=min(dis[v][u],w);
        mp[u][v]=min(mp[u][v],w);
        mp[v][u]=min(mp[v][u],w);
    }
	int ans = inf;
	 for(int k=1;k<=n;k++)
	 {
		for(int i=1;i<k;i++)
			for(int j=i+1;j<k;j++)
				ans = min(ans,dis[i][j]+mp[i][k]+mp[k][j]);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++){
				dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
				dis[j][i] = dis[i][j];
			}

	}
	if(ans==inf)
        cout<<"No solution."<<endl;
	else
        cout<<ans<<endl;
    return 0;
}
举报

相关推荐

刷题练习3

nss刷题(3)

刷题笔记2

C语言刷题3

#刷题 2.Manger

力扣刷题(2)

C语言刷题笔记3

0 条评论