zoukankan      html  css  js  c++  java
  • GPLT L3-028.森森旅游

    建两个图,正图和反图。

    正图里的边权是现金,反图里的边权是旅游金。

    然后分别以1为起点在正图上跑最短路,以n为起点在反图上跑最短路。

    这样计算出每个点的答案,取最小,不带修改的情况就做完了。

    带修改的情况放线段树上维护一下就好了。

    注意巨大坑点:不保证图连通。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+100;
    typedef long long ll;
    const ll inf=1e18;
    vector<pair<int,int> > g1[maxn];//原图
    vector<pair<int,int> > g2[maxn];//反图
    
    int n,m,q;
    int a[maxn];//汇率 
    
    ll d1[maxn];//1到每个点的现金最短路
    ll d2[maxn];//每个点到n的旅游金最短路 
    struct qnode {
    	//dijkstra辅助结构体 
    	int v;
    	ll w;
    	qnode (int vv,ll ww) {
    		v=vv;
    		w=ww;
    	}
    	bool operator < (const qnode &r) const {
    		return w>r.w;//结构体重载运算符
    		//因为STL的优先队列默认是大顶堆,所以这里反着写运算符 
    	}
    };
    int vis[maxn];//dij标记是否确定最短路
    void dij1 (int s) {
    	//以1为起点,在正图上跑第一遍最短路
    	for (int i=1;i<=n;i++) d1[i]=inf,vis[i]=0;
    	d1[s]=0;
    	priority_queue<qnode> q;//堆优化 
    	q.push(qnode(s,d1[s]));
    	while (q.size()) {
    		qnode tt=q.top();
    		q.pop();
    		int u=tt.v;
    		if (vis[u]) continue;
    		vis[u]=1;
    		for (pair<int,int> it:g1[u]) {
    			int v=it.first;
    			if (vis[v]) continue;
    			if (d1[u]+it.second<d1[v]) {
    				d1[v]=d1[u]+it.second;
    				q.push(qnode(v,d1[v]));
    			}
    		}
    	} 
    } 
    void dij2 (int s) {
    	//以n为起点,在反图上跑第二遍最短路
    	for (int i=1;i<=n;i++) d2[i]=inf,vis[i]=0;
    	d2[s]=0;
    	priority_queue<qnode> q;//堆优化 
    	q.push(qnode(s,d2[s]));
    	while (q.size()) {
    		qnode tt=q.top();
    		q.pop();
    		int u=tt.v;
    		if (vis[u]) continue;
    		vis[u]=1;
    		for (pair<int,int> it:g2[u]) {
    			int v=it.first;
    			if (vis[v]) continue;
    			if (d2[u]+it.second<d2[v]) {
    				d2[v]=d2[u]+it.second;
    				q.push(qnode(v,d2[v]));
    			}
    		}
    	} 
    } 
    ll ans[maxn];//每个点的答案
    struct node {
    	int l,r;
    	ll sum;//区间最小值 
    }segTree[maxn<<2];
    void build (int i,int l,int r) {
    	segTree[i].l=l;
    	segTree[i].r=r;
    	if (l==r) {
    		segTree[i].sum=ans[l];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(i<<1,l,mid);
    	build(i<<1|1,mid+1,r);
    	segTree[i].sum=min(segTree[i<<1].sum,segTree[i<<1|1].sum);
    }
    void up (int i,int p) {
    	if (segTree[i].l==p&&segTree[i].r==p) {
    		segTree[i].sum=d1[p]+d2[p]/a[p]+(d2[p]%a[p]>0?1:0);
    		return;
    	}
    	int mid=(segTree[i].l+segTree[i].r)>>1;
    	if (p<=mid) up(i<<1,p);
    	if (p>mid) up(i<<1|1,p);
    	segTree[i].sum=min(segTree[i<<1].sum,segTree[i<<1|1].sum);
    }
    int main () {
    	scanf("%d%d%d",&n,&m,&q);
    	for (int i=1;i<=m;i++) {
    		int A,B,C,D;
    		scanf("%d%d%d%d",&A,&B,&C,&D);
    		g1[A].push_back(make_pair(B,C));
    		g2[B].push_back(make_pair(A,D));
    	}
    	for (int i=1;i<=n;i++) scanf("%d",a+i);
    	dij1(1);
    	dij2(n);
    	for (int i=1;i<=n;i++) {
    		if (d1[i]==inf||d2[i]==inf) {
    			ans[i]=1e18;
    			continue;
    		}
    		ans[i]=d1[i]+d2[i]/a[i]+(d2[i]%a[i]>0?1:0);
    	}
    	build(1,1,n);//线段树建树
    	while (q--) {
    		int x,y;
    		scanf("%d%d",&x,&y);
    		a[x]=y;
    		if (d1[x]!=inf&&d2[x]!=inf)
    			up(1,x);//单点更新
    		printf("%lld
    ",segTree[1].sum); 
    	} 
    }
  • 相关阅读:
    ACE-6.1.0 linux 下的编译与安装步骤
    tcp_sync_server and tcp_sync_client
    网络服务器操作命令telnet
    eclipse CDT unresolved inclusion
    qt安装--this Qt version uses an unsupported makefile
    java指令详解
    (8) tomcat中管理领域、角色及用户
    (7) 将tomcat HTTP连接器启动在80端口(jsvc使用详解)
    10月16日面试总结
    MYSQL查询的四种情况
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14726600.html
Copyright © 2011-2022 走看看