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旅行的主要内容,如果未能解决你的问题,请参考以下文章