您的位置:首页 > 编程语言 > Go语言

[USACO13DEC]假期计划(黄金)Vacation Planning (gold)

2017-08-15 14:50 603 查看
题目翻译不好,这里给出一份

题目背景

Awson是某国际学校信竞组的一只大佬。由于他太大佬了,于是干脆放弃了考前最后的集训,开车(他可是老司机)去度假。离开学校前,他打开地图,打算做些规划。

题目描述

他发现整个地图中有N(1<=N<=20000)个地点。对于所有的路线,指定了其中K(1<=K<=200,K<=N)个地点作为收费站。他设计了M(1<=M<=20000 )种单向的路线,第i条路线从地点Ui至Vi收费为Di(1<=Di<=10000)。路线保证Ui或Vi至少有一个是收费站,且Ui≠Vi,任意两个地点至多有一条路线。现在Awson准备进行规划。共提出Q(1<=Q<=50000)个询问,其中第i个询问是从地点Ai至地点Bi。请帮助他计算,每个请求是否满足(是否从地点Ai至地点Bi有可行路线),并计算:能满足的度假询问的最小费用总和。

输入输出格式

输入格式:

第1行:四个整数N,M,K,Q

第2~M+1行:三个整数Ui,Vi,Di

第M+2~M+K+1行:收费站的编号X (0<=X<=N)

第M+K+2~M+K+Q+1:两个整数,度假询问Ai,Bi

输出格式:

第1行:能够满足的度假询问数

第2行:能满足的度假询问的最小费用总和

输入输出样例

输入样例:

3 3 1 2

1 2 10

2 3 10

2 1 5

2

1 3

3 1

输出样例:

1

20

说明

样例解释:

第1个询问,路线设计为1->2->3,费用为20

第2个询问,无法满足

数据规模:

30%的数据有N<=100;

100%的数据有1<=N,M<=20000,1<=Q<=50000。

[b]题解:[/b]

[b]n很大,就算能O(1)求最短路也不行[/b]

[b]但我们发现k很小,而且每条边至少有一个收费站[/b]

[b]假设问u,v之间的最小距离,就是与u相邻的收费站与v的距离+边权[/b]

[b]为包括u是收费站的情况,加入(u,u,0)边,修改部分会在代码中标记[/b]

[b]题目转化为了求每个收费站到每个点的距离,用SPFA[/b]

[b]复杂度为O(km+k*k)[/b]

[b]询问部分可知一个点相邻的收费站最多为k,所以[/b]

[b]询问复杂度为O(Q*k)[/b]

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Node
{
int next,dis,to;
}edge[200001];
int head[100001],num,dist[201][20001],q[1000001],n,m,k,Q,p[10001],dis[301][301],b[100001],ans,cnt;
bool vis[100001];
void add(int u,int v,int d)
{
num++;
edge[num].next=head[u];
head[u]=num;
edge[num].to=v;
edge[num].dis=d;
}
void SPFA(int st,int j)
{int h,t,i;;
memset(dist[j],127,sizeof(dist[j]));
memset(vis,0,sizeof(vis));
q[1]=st;
h=0;t=1;
dist[j][st]=0;
while (h<t)
{
h++;
h%=1000000;
int u=q[h];
vis[u]=0;
for (i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if (dist[j][v]>dist[j][u]+edge[i].dis)
{
dist[j][v]=dist[j][u]+edge[i].dis;
if (!vis[v])
{
t++;
t%=1000000;
q[t]=v;
vis[v]=1;
}
}
}
}
for (i=1;i<=k;i++)
if (i!=j)
dis[j][i]=dist[j][p[i]];
}
int main()
{int i,j,u,v,d;
cin>>n>>m>>k>>Q;
edge[0].next=-1;
for (i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&d);
add(u,v,d);
}
for (i=1;i<=k;i++)
{
scanf("%d",&p[i]);
b[p[i]]=i;
}
for (i=1;i<=k;i++)
{
SPFA(p[i],i);
}
while (Q--)
{
scanf("%d%d",&u,&v);
int s=1e9,x,y;
if (b[u]&&b[v])
{
s=dis[b[u]][b[v]];
}
else
for (i=head[u];i!=-1;i=edge[i].next)
{
82                 if (b[u]) i=0;
83                 if (i==0) x=u;
84                 else x=edge[i].to;
if (b[x])
{
if (s>edge[i].dis+dist[b[x]][v])
s=edge[i].dis+dist[b[x]][v];
}
}
//cout<<s<<endl;
if (s<1e9)
ans+=s,cnt++;
}
cout<<cnt<<endl<<ans;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: