• 「JOI 2018 Final」月票购买


    JOI 所住的城市有 N 个车站,分别编号为 1::N。有 M条铁路,编号为 1..M。第I 条铁路双向连接车站 A 与车站 B,乘车费用为 C。

    JOI 住在车站 S 附近,而 JOI 所在的 IOI 高中在车站 T 附近。他打算买一张月票往返这两个车站。当他买这张月票时,他需要选择一条在车站 S 与车站 T之间的乘车费用最小的路径。有了这张月票,JOI 可以无需额外费用,双向通过任意所选路径包含的铁路。

    JOI 经常去在车站 U 与车站 V 附近的书店,因此他希望能买一张月票使得从车站 U 到车站 V 的花费最小。

    当他要从车站 U 去往车站 V 时,他会选择一条从车站 U 到车站 V 的路径。对于路径上的每段铁路,如果这段铁路在月票指定的路径范围内,则费用为 0 ,否则费用为C 。每段铁路的费用和为 JOI 从车站 U 到车站 V 的总费用。

    他想要知道,如果他买月票时选择了一条合适的路线,从车站 U到车站 V 的最小费用是多少。

    你需要编写一个程序计算最小费用。

    解:
    真是一道好题目啊
    首先我们有一个贪心策略 首先将所有最短路上的边设置为有向边 然后再跑最短路 但是这样做有问题 因为两条路可能在两条最短路上 这就很难受了
    但是!!! 注意到 这是一条连续的路径 最短路的边一定是DAG DAG上搞事情 DP啊 最短路的题目 不是建立图就是考DP 想DP 而且是一个在最短路上搞的DP 注意到 题目的条件是在一条最短路上 而一条最短路的条件为 (dis[u]==dis[v]+le[i])然后我们就可以DP了 在图上的DP一定是在一个top序列上DP 于是我们就想到了 将最短路作为top序列进行DP 具体实现可以利用(dij)来做

    topp序列DAG DP

    queue<int> q;
    void DP() {
        for (int i = 1; i <= n; fu[i] = vu[i], fv[i] = vv[i], i++)
            if (!deg[i])
                q.push(i);
        while (q.size()) {
            int x = q.front();
            q.pop();
            ans = min(ans, min(fv[x] + vu[x], fu[x] + vv[x]));
            for (int i = las[x]; i; i = pre[i]) {
                int y = to[i];
                fu[y] = min(fu[y], fu[x]), fv[y] = min(fv[y], fv[x]);
                if (--deg[y] == 0)
                    q.push(y);
            }
        }
    }
    

    code:

    //
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define inf (ll)(1e17)
    #define maxnn 2010000
    ll las[maxnn],nex[maxnn],le[maxnn],tot,en[maxnn];
    
    ll zlas[maxnn],znex[maxnn],zle[maxnn],ztot,zen[maxnn];
    ll flas[maxnn],fnex[maxnn],fle[maxnn],ftot;
    ll dis1[maxnn],dis2[maxnn],dis3[maxnn],dis4[maxnn];
    ll n,m,s,t,u,v;
    struct node
    {
    	int st,en;
    	ll l;
    	ll d;
    }ed[maxnn];
    int cnt;
    
    void add(int a,int b,ll c)
    {
    	en[++tot]=b;
    	nex[tot]=las[a];
    	las[a]=tot;
    	le[tot]=c;
    }
    
    void zadd(int a,int b,ll c)
    {
    	zen[++ztot]=b;
    	znex[ztot]=zlas[a];
    	zlas[a]=ztot;
    	zle[ztot]=c;
    }
    typedef pair<ll ,int > P;
    priority_queue<P ,vector<P>,greater<P> > Q;
    void dij(ll *dis,int v)
    {
    	for(int i=1;i<=n;i++)
    	{
    		dis[i]=inf;
    	}
    	dis[v]=0;
    	Q.push(make_pair(dis[v],v));
    	while(Q.size())
    	{
    		P s=Q.top();
    		Q.pop();
    		if(s.first!=dis[s.second]) continue;
    		for(int i=las[s.second];i;i=nex[i])
    		{
    			int u=en[i];
    			if(dis[u]>dis[s.second]+le[i])
    			{
    				dis[u]=dis[s.second]+le[i];
    				Q.push(make_pair(dis[u],u));
    			}
    		}
    	}
    }
    ll dis[maxnn];
    ll f[maxnn][3];
    ll ans=111111111000000;
    void ddij(int v)
    {
    	for(int i=1;i<=n;i++)
    	{
    		f[i][0]=f[i][1]=inf;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		dis[i]=inf;
    	}
    	dis[v]=0;
    	f[v][0]=dis3[v];
    	f[v][1]=dis4[v];
    	Q.push(make_pair(dis[v],v));
    	while(Q.size())
    	{
    		P s=Q.top();
    		Q.pop();
    		if(s.first!=dis[s.second]) continue;
    		for(int i=zlas[s.second];i;i=znex[i])
    		{
    			int u=zen[i];
    			if(dis[u]==dis[s.second]+zle[i])
    			{
    				dis[u]=dis[s.second]+zle[i];
    				f[u][0]=min(f[u][0],min(f[s.second][0],dis3[u]));
    				f[u][1]=min(f[u][1],min(f[s.second][1],dis4[u]));
    			}
    			if(dis[u]>dis[s.second]+zle[i])
    			{
    				dis[u]=dis[s.second]+zle[i];
    				f[u][0]=min(f[s.second][0],dis3[u]);
    				f[u][1]=min(f[s.second][1],dis4[u]);
    				Q.push(make_pair(dis[u],u));
    			}
    		}
    	}
    }
    int main()
    {
    	ll x,y,z;
    	scanf("%lld%lld%lld%lld%lld%lld",&n,&m,&s,&t,&u,&v);
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%lld%lld%lld",&x,&y,&z);
    		add(x,y,z);
    		add(y,x,z);
    		ed[++cnt].st=x;
    		ed[cnt].en=y;
    		ed[cnt].l=z;
    	}
    	dij(dis1,s);
    	dij(dis2,t);
    	dij(dis3,u);
    	dij(dis4,v);
    	for(int i=1;i<=cnt;i++)
    	{
    		if(dis1[ed[i].st]+dis2[ed[i].en]+ed[i].l==dis1[t])
    		{
    			zadd(ed[i].st,ed[i].en,ed[i].l);
    		}
    		if(dis1[ed[i].en]+dis2[ed[i].st]+ed[i].l==dis1[t])
    		{
    			zadd(ed[i].en,ed[i].st,ed[i].l);
    		}
    	}
    	ddij(s);
    	for(int i=1;i<=n;i++)
    	{
    		ans=min(ans,f[i][1]+dis3[i]);
    		ans=min(ans,f[i][0]+dis4[i]);
    	}
    	ans=min(ans,dis3[v]);
    	cout<<ans;
    	
    }
    
    
  • 相关阅读:
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    day 67 Django基础三之视图函数
    day 66 Django基础二之URL路由系统
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11810672.html
Copyright © 2020-2023  润新知