bzoj4093: [Usaco2013 Dec]Vacation Planning

bzoj4093: [Usaco2013 Dec]Vacation Planning

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 81  Solved: 38
[Submit][Status][Discuss]

Description

 

Bovinia设计了连接N (1 < = N < = 20,000)个农场的航班。对于任何航班,指定了其中的k个农场作为枢纽。 (1 < = K <= 200 , K < = N)。
目前,共有M种单向航班( 1 < = M < = 20,000 ),第i个航班从农场u_i至农场v_i花费d_i ( 1 < = d_i < =10,000 )美元。航班保证u_i或者v_i至少有一个是枢纽,任意两个农场至多只有一个航班,保证u_i≠v_i。
Bessie负责票务服务。共收到Q个度假请求,(1 < = Q < = 50,000),其中第i个请求是从农场a_i至农场b_i 。请帮助她计算,每个请求是否满足 ,并计算:能满足的度假请求的最小费用总和。

 

 

Input

 第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

 

 

Output

第1行:能够满足的度假请求数
第2行:能满足的度假请求的最小费用总和
 

 

Sample Input

3 3 1 2
1 2 10
2 3 10
2 1 5
2
1 3
3 1

Sample Output

1
20
【样例解释】
第1个请求,航线设计为1->2->3,费用为20
第2个请求,无法满足

HINT

 

Source

Gold

 

 

题解:

其实这题有双倍经验 同bzoj4097 然而数据范围大了一坨

跟上一题一样的 询问中的路径肯定会经过至少一个枢纽

设枢纽为x 则mincost=min{dis[u][x]+dis[x][v]}

由于是单向边 所以要把边反过来再跑一次最短路求出各点到枢纽的距离。。。

对于每个询问。。。枚举枢纽找出最小值即可

代码:

 1 #include<bits/stdc++.h>
 2 #define rep(i,l,r) for(int i=l;i<=r;++i)
 3 using namespace std;
 4 typedef long long ll;
 5 const int N=20023,inf=4e8;
 6 int dis[2][210][N],u,v,w,n,m,K,Q,s[N],head[N],tot,a[N],b[N],c[N],cnt;
 7 bool in[N];
 8 ll ans,mn;
 9 struct zs{
10     int to,next;
11     ll w;
12 }e[N];
13 inline void ins(int u,int v,int w){
14     e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].w=w;
15 }
16 inline void spfa(int flag,int num){
17      queue<int>q; q.push(s[num]); dis[flag][num][s[num]]=0; in[s[num]]=1;
18      while(!q.empty()){
19          int x=q.front(); q.pop();
20          for(int k=head[x];k;k=e[k].next) if(dis[flag][num][x]+e[k].w<dis[flag][num][e[k].to]){
21              dis[flag][num][e[k].to]=dis[flag][num][x]+e[k].w;
22              if(!in[e[k].to]){
23                  in[e[k].to]=1;
24                  q.push(e[k].to);
25              }
26          }
27          in[x]=0;
28      }
29 }
30 int main(){
31     memset(dis,60,sizeof dis);
32     scanf("%d%d%d%d",&n,&m,&K,&Q);
33     rep(i,1,m) scanf("%d%d%d",&a[i],&b[i],&c[i]),ins(a[i],b[i],c[i]);
34     rep(i,1,K) scanf("%d",&s[i]);
35     rep(i,1,K) spfa(0,i);
36     memset(head,0,sizeof head); tot=0;
37     rep(i,1,m) ins(b[i],a[i],c[i]);
38     rep(i,1,K) spfa(1,i);
39     ans=0;
40     while(Q--){
41         scanf("%d%d",&u,&v);
42         mn=inf;
43         rep(i,1,K) mn=min(mn,(ll)(dis[0][i][v]+dis[1][i][u]));
44         if(mn!=inf)    ++cnt,ans+=mn;
45     }
46     printf("%d\n%lld\n",cnt,ans);
47 }
View Code

 

 

跑得极慢QAQ

 

posted @ 2016-08-11 21:56  Bloodline  阅读(512)  评论(1编辑  收藏  举报