• G. Reducing Delivery Cost 思维+最短路


    G. Reducing Delivery Cost 思维+最短路

    题目大意:

    n个点,m条边,q条路经,每条路径有一个起点一个终点,你最多可以选择删掉一条边,问删完之后q条路经距离的最小值之和,距离表示起点到终点的最短距离。

    题解:

    先预处理任意两个点之间的最短距离,枚举这m条边,查删掉之后的距离,求最小值。

    注意:如果一条边删去,那么最短距离的更新有两种可能

    • 删掉前后都不是最短距离的一部分,最短距离不变
    • 删掉之后成为了最短距离的一部分,那么就是原来的点到两端的距离+0

    最后的复杂度就是 (O(n*m+m*k*logn))

    这个题目主要要明白,一条边变成0之后,应该如何更新这个最短路。

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 1010;
    typedef long long ll;
    int head[maxn],flag[maxn<<1],to[maxn<<1],nxt[maxn<<1],cnt,cost[maxn],w[maxn<<1];
    void add(int u,int v,int i,int c){
    	++cnt,to[cnt] = v,flag[cnt] = i,nxt[cnt] = head[u],w[cnt] = c,head[u] = cnt;
    	++cnt,to[cnt] = u,flag[cnt] = i,nxt[cnt] = head[v],w[cnt] = c,head[v] = cnt;
    }
    struct node{
    	int u,d;
    	node(int u=0,int d=0):u(u),d(d){}
    	bool operator<(const node&a)const{
    		return a.d<d;
    	}
    };
    int vis[maxn],d[maxn][maxn],n,m,k,num[maxn];
    priority_queue<node>que;
    void dij(int s){
    	int pos = s;
    	while(!que.empty()) que.pop();
    	for(int i=1;i<=n;i++) d[pos][i] = inf,vis[i] = false;
    	que.push(node(s,0));
    	d[pos][s] = 0;
    	while(!que.empty()){
    		node x = que.top();que.pop();
    		int u = x.u;
    		if(vis[u]) continue;
    		vis[u] = true;
    		for(int i=head[u];i;i=nxt[i]){
    			int v = to[i];
    			if(d[pos][v]>d[pos][u]+w[i]){
    				d[pos][v] = d[pos][u] + w[i];
    				que.push(node(v,d[pos][v]));
    			}
    		}
    	}
    }
    int gx[maxn],gy[maxn],ux[maxn],uy[maxn],uw[maxn];
    int main(){
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=1;i<=m;i++){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,i,w);
    		cost[i] = w,ux[i] = u,uy[i] = v,uw[i]  =w;
    	}
    	for(int i=1;i<=k;i++){
    		scanf("%d%d",&gx[i],&gy[i]);
    		dij(gx[i]),dij(gy[i]);
    	}
    	ll ans = inf64;
    	for(int i=1;i<=m;i++){
    		ll sum = 0;
    		int x = ux[i],y = uy[i],w = uw[i];
    		for(int j=1;j<=k;j++){
    			int u = gx[j],v = gy[j];
    			sum += min(min(d[u][x]+d[v][y],d[u][y]+d[v][x]),d[u][v]);
    		}
    		ans = min(ans,sum);
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    极客技术专题【011期】:EasyUI初级教程
    帮助自定义选择框样式的Javascript
    利用HTML5与jQuery技术创建一个简单的自动表单完成
    30个iPhone健康应用帮助你保持身体健康
    如何构建下拉滑动式响应导航菜单
    推荐十款来自极客标签的超棒前端特效[第十三期]
    重新设计网站的10点建议
    创建CSS3警示框渐变动画
    17种新型的响应式开发框架
    使用jQuery创建模态窗口登陆效果
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13866291.html
Copyright © 2020-2023  润新知