zoukankan      html  css  js  c++  java
  • 【YbtOJ#20238】最优路线

    题目

    题目链接:https://www.ybtoj.com.cn/contest/68/problem/2
    给定一张 (n) 个点 (m) 条边的无向图,无重边无自环,每个点有点权,每条边有边权。

    我们定义一条路径的权值,为这条路径经过的点权最大值乘以边权最大值。

    对于每个点对 ((u,v)),你都要求出 (u,v) 之间的权值最小的路径的权值。

    思路

    按点权从小到大枚举点。
    假设当前枚举到点 (x),从 (x) 开始跑一遍 Prim,求出 (x) 到每一个点的路径中路径长度最小值。
    然后枚举所有点对 ((i,j)),用 (x) 去更新 ((i,j)) 的贡献,显然是 (max(mind[i],mind[j]) imes a[x])
    时间复杂度 (O(n^3))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=510;
    int n,m,pre[N],d[N],mind[N],dis[N][N];
    ll ans[N][N];
    bool vis[N],flag[N];
    
    struct node
    {
    	int a,id;
    }a[N];
    
    bool cmp(node x,node y)
    {
    	return x.a<y.a;
    }
    
    void prim(int s)
    {
    	memset(vis,0,sizeof(vis));
    	memset(pre,0,sizeof(pre));
    	memset(mind,0,sizeof(mind));
    	memset(d,0x3f3f3f3f,sizeof(d));
    	d[s]=0;
    	for (int k=1;k<=n;k++)
    	{
    		int p=0;
    		for (int i=1;i<=n;i++)
    			if (flag[i] && !vis[i] && (d[i]<d[p] || !p)) p=i;
    		vis[p]=1; mind[p]=max(d[p],mind[pre[p]]);
    		for (int i=1;i<=n;i++)
    			if (flag[i] && !vis[i] && d[i]>dis[i][p])
    				d[i]=dis[i][p],pre[i]=p;
    	}
    }
    
    int main()
    {
    	freopen("path.in","r",stdin);
    	freopen("path.out","w",stdout);
    	memset(dis,0x3f3f3f3f,sizeof(dis));
    	memset(ans,0x3f3f3f3f,sizeof(ans));
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i].a);
    		a[i].id=i;
    	}
    	for (int i=1,x,y,z;i<=m;i++)
    	{
    		scanf("%d%d%d",&x,&y,&z);
    		dis[x][y]=dis[y][x]=z;
    	}
    	sort(a+1,a+1+n,cmp);
    	for (int i=1;i<=n;i++)
    	{
    		int x=a[i].id;
    		flag[x]=1;
    		prim(x);
    		for (int j=1;j<=n;j++)
    			for (int k=1;k<=n;k++)
    				if (flag[j] && flag[k])
    					ans[j][k]=ans[k][j]=min(ans[j][k],1LL*max(mind[j],mind[k])*a[i].a);
    	}
    	for (int i=1;i<=n;i++)
    	{
    		for (int j=1;j<=n;j++)
    			if (ans[i][j]<1e18) printf("%lld ",ans[i][j]);
    				else printf("-1 ");
    		printf("
    ");
    	}
    }
    
  • 相关阅读:
    C# WinForm开发系列
    C# Tcp协议收发数据(TCPClient发,Socket收)
    Tcpclient简单聊天程序
    大白话系列之C#委托与事件讲解大结局
    大白话系列之C#委托与事件讲解(三)
    poj3009
    poj 3083
    poj 2488
    POJ 3320
    poj 3061
  • 原文地址:https://www.cnblogs.com/stoorz/p/14074857.html
Copyright © 2011-2022 走看看