JZOJ3400旅行

Posted horizonwd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JZOJ3400旅行相关的知识,希望对你有一定的参考价值。

description

从前有一位旅者,他想要游遍天下所有的景点。这一天他来到了一个神奇的王国:在这片土地上,有n个城市,从1到n进行编号。王国中有m条道路,第i条道路连接着两个城市ai,bi,由于年代久远,所有的道路都已经不能使用。如果要修复第i条道路,需要wi的时间。为了更好的旅行,旅者想要将某些道路修复,使得1号城市能够到达n号城市,2号城市能够到达n-1号城市..k号城市能够到达n-k+1号城市。为了满足他的要求,请问最少需要多少时间去修复道路。无解请输出-1。


analysis

  • 可以\(O(4!)\)暴力枚举这\(k\)组关系的顺序

  • 然后依次跑\(SPFA\),每跑一次把最短路上的边权标零,记录最小值即可

  • 听着是不是没有问题?其实这是水法,连拍都过不了233

  • 正解斯坦纳树,我还不会


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define MAXN 10005
#define MAXM 20005
#define INF 1000000007
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define rep(i,a) for (reg i=last[a];i;i=next[i])

using namespace std;

ll last[MAXM],next[MAXM],tov[MAXM],len[MAXM];
ll f[5],pre[MAXN][2],dis[MAXN];
bool bo[5],bz[MAXN];
ll n,m,k,tot,ans=INF;
deque<ll>q;

struct edge

    ll x,y,z;   
a[MAXN];

inline ll read()

    ll x=0,f=1;char ch=getchar();
    while (ch<'0' || '9'<ch)if (ch=='-')f=-1;ch=getchar();
    while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;

inline ll min(ll x,ll y)return x<y?x:y;
inline void link(ll x,ll y,ll z)

    next[++tot]=last[x],last[x]=tot,tov[tot]=y,len[tot]=z;  

inline ll spfa(ll S,ll T)

    memset(bz,1,sizeof(bz));
    memset(pre,0,sizeof(pre));
    memset(dis,64,sizeof(dis));
    q.push_back(S),bz[S]=dis[S]=0;
    while (!q.empty())
    
        ll now=q.front();q.pop_front(),bz[now]=1;
        rep(i,now)if (dis[now]+len[i]<=dis[tov[i]])
        
            dis[tov[i]]=dis[now]+len[i],pre[tov[i]][0]=now,pre[tov[i]][1]=i;
            if (bz[tov[i]])
            
                bz[tov[i]]=0;
                if (!q.empty() && dis[tov[i]]<dis[q.front()])q.push_front(tov[i]);
                    else q.push_back(tov[i]);
            
        
    
    return dis[T];

inline void dfs(ll x)

    if (x>k)
    
        ll cnt=0;
        memset(last,0,sizeof(last)),memset(next,0,sizeof(next)),
        memset(tov,0,sizeof(tov)),memset(len,0,sizeof(len)),tot=1;
        fo(i,1,m)link(a[i].x,a[i].y,a[i].z),link(a[i].y,a[i].x,a[i].z);
        fo(i,1,k)
        
            ll beg=f[i],end=n-f[i]+1,pos=end;
            ll tmp=spfa(beg,end);
            if (tmp>=INF)return;cnt+=tmp;
            while (pos!=beg)len[pre[pos][1]]=len[pre[pos][1]^1]=0,pos=pre[pos][0];
        
        ans=min(ans,cnt);
        return;
    
    fo(i,1,k)if (bo[i])bo[i]=0,f[x]=i,dfs(x+1),bo[i]=1;

int main()

    n=read(),m=read(),k=read();
    fo(i,1,m)a[i].x=read(),a[i].y=read(),a[i].z=read();
    memset(bo,1,sizeof(bo)),dfs(1);
    if (ans<INF)printf("%lld\n",ans);
    else printf("-1\n");
    return 0;

以上是关于JZOJ3400旅行的主要内容,如果未能解决你的问题,请参考以下文章

[并差集] Jzoj P5794 旅行

携程旅行的APP怎么用

优化旅行推销员算法(时间旅行者算法)

杂项旅行旅行必备

旅行路线

翠明假期旅行社好吗?美国华人旅行社跟团游报哪个?