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
题解:
其实这题有双倍经验 同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 }
跑得极慢QAQ