码迷,mamicode.com
首页 > 其他好文 > 详细

[USACO 13DEC]Vacation Planning(gold)

时间:2017-08-15 15:12:50      阅读:256      评论:0      收藏:0      [点我收藏+]

标签:numbers   关键点   mini   live   current   panel   most   getchar   getch   

Description

Air Bovinia operates flights connecting the N farms that the cows live on (1 <= N <= 20,000). As with any airline, K of these farms have been designated as hubs (1 <= K <= 200, K <= N).

Currently, Air Bovinia offers M one-way flights (1 <= M <= 20,000), where flight i travels from farm u_i to farm v_i and costs d_i (1 <= d_i <= 10,000) dollars. As with any other sensible airline, for each of these flights, at least one of u_i and v_i is a hub. There is at most one direct flight between two farms in any given direction, and no flight starts and ends at the same farm.

Bessie is in charge of running the ticketing services for Air Bovinia. Unfortunately, while she was away chewing on delicious hay for a few hours, Q one-way travel requests for the cows‘ holiday vacations were received (1 <= Q <= 50,000), where the ith request is from farm a_i to farm b_i.

As Bessie is overwhelmed with the task of processing these tickets, please help her compute whether each ticket request can be fullfilled, and its minimum cost if it can be done.

To reduce the output size, you should only output the total number of ticket requests that are possible, and the minimum total cost for them. Note that this number might not fit into a 32-bit integer.

是n个点m条有向边,求两两之间的最短路,要求路径上必须经过编号1~k的至少一个点

Input

  • Line 1: The integers N, M, K, and Q.

  • Lines 2..M + 1: Line i+1 contains u_i, v_i, and d_i. (1 <= u_i, v_i <= N, u_i != v_i)

  • Lines M + 2..M + K + 1: Each of these lines contains the ID of a single hub (in the range 1..N).

  • Lines M + K + 2..M + K + Q + 1: Two numbers per line, indicating a request for a ticket from farm a_i to b_i. (1 <= a_i, b_i <= N, a_i != b_i)

Output

  • Line 1: The number of ticket requests that can be fullfilled.

  • Line 2: The minimum total cost of fulling the possible ticket requests

Sample Input

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

Sample Output

1 
20 

Hint

For the first flight, the only feasible route is 1->2->3, costing 20. There are no flights leaving farm 3, so the poor cows are stranded there.

题解

显然是一道求多源最短路的题,而总的点数远远超过了$floyd$的承受范围。

我们用分治的思想,注意到题中所有边都是与“关键点”即收费站相连的,显然我们可以考虑对于这些点进行$floyd$。

对于非关键点的点,我们可以枚举,并在之前$floyd$处理完的“块”内求一遍单源最短路,注意与枚举的点相连的边是“出边”还是“入边”。

处理答案时,注意点要分是在“块”内还是“块”外。

  1 #include<cmath>
  2 #include<queue>
  3 #include<ctime>
  4 #include<stack>
  5 #include<cstdio>
  6 #include<string>
  7 #include<cstdlib>
  8 #include<cstring>
  9 #include<iostream>
 10 #include<algorithm>
 11 #define LL long long
 12 using namespace std;
 13 const int N=20000;
 14 int INF;
 15 
 16 struct tt
 17 {
 18     int to,next,cost;
 19 }edge[N+5];
 20 int path[N+5],top;
 21 int n,m,k,q,u,v,d;
 22 int x[205],num[N+5];
 23 int map[205][205];
 24 int in[N+5][205],out[205][N+5];
 25 
 26 void Count_in();
 27 void Count_out();
 28 void Floyd();
 29 void Build();
 30 inline void Add(int x,int y,int c);
 31 inline int my_min(int x,int y);
 32 inline int Read();
 33 
 34 int main()
 35 {
 36     n=Read();m=Read();k=Read();q=Read();
 37     for (int i=1;i<=m;i++)
 38     {
 39         u=Read();v=Read();d=Read();
 40         Add(u,v,d);
 41     }
 42     for (int i=1;i<=k;i++)
 43     {
 44         x[i]=Read();
 45         num[x[i]]=i;
 46     }
 47     Floyd();
 48     Count_in();
 49     Count_out();
 50     int cnt=0,sum=0,ans=2*INF,x,y;
 51     for (int i=1;i<=q;i++)
 52     {
 53         x=Read();y=Read();
 54         if (num[x]&&num[y]) {if (map[num[x]][num[y]]<INF) cnt++,sum+=map[num[x]][num[y]];}
 55         else if (num[x]) {if (out[num[x]][y]<INF) cnt++,sum+=out[num[x]][y];}
 56         else if (num[y]) {if (in[x][num[y]]<INF) cnt++,sum+=in[x][num[y]];}
 57         else
 58         {
 59             int ans=2*INF;
 60             for (int j=1;j<=k;j++) if (in[x][j]+out[j][y]<ans) ans=in[x][j]+out[j][y];
 61             if (ans<INF) cnt++,sum+=ans;
 62         }
 63     }
 64     printf("%d\n%d\n",cnt,sum);
 65     return 0;
 66 }
 67 
 68 inline void Add(int x,int y,int c)
 69 {
 70     edge[++top].to=y;
 71     edge[top].cost=c;
 72     edge[top].next=path[x];
 73     path[x]=top;
 74 }
 75 void Floyd()
 76 {
 77     memset(map,127/3,sizeof(map));
 78     Build();
 79     for (int p=1;p<=k;p++)
 80         for (int i=1;i<=k;i++)
 81             for (int j=1;j<=k;j++)
 82                 if (map[i][j]>map[i][p]+map[p][j])
 83                     map[i][j]=map[i][p]+map[p][j];
 84 }
 85 void Build()
 86 {
 87     for (int i=1;i<=k;i++)
 88         for (int j=path[x[i]];j;j=edge[j].next)
 89             if (!num[edge[j].to])
 90                 for (int p=path[edge[j].to];p;p=edge[p].next)
 91                     map[i][num[edge[p].to]]=my_min(map[i][num[edge[p].to]],edge[j].cost+edge[p].cost);
 92             else map[i][num[edge[j].to]]=my_min(map[i][num[edge[j].to]],edge[j].cost);
 93 }
 94 void Count_in()
 95 {
 96     memset(in,127/3,sizeof(in));INF=in[0][0];
 97     for (int i=1;i<=n;i++) if (!num[i])
 98     {
 99         for (int j=path[i];j;j=edge[j].next)
100         {
101             if (in[i][num[edge[j].to]]>edge[j].cost)
102                 in[i][num[edge[j].to]]=edge[j].cost;
103             for (int p=1;p<=k;p++) if (in[i][p]>map[num[edge[j].to]][p]+edge[j].cost)
104                 in[i][p]=map[num[edge[j].to]][p]+edge[j].cost;
105         }
106     }
107 }
108 void Count_out()
109 {
110     memset(out,127/3,sizeof(out));
111     for (int i=1;i<=k;i++)
112     {
113         for (int j=path[x[i]];j;j=edge[j].next) if (!num[edge[j].to])
114         {
115             if (out[i][edge[j].to]>edge[j].cost)
116                 out[i][edge[j].to]=edge[j].cost;
117             for (int p=1;p<=k;p++) if (out[p][edge[j].to]>map[p][i]+edge[j].cost)
118                 out[p][edge[j].to]=map[p][i]+edge[j].cost;
119         }
120     }
121 }
122 inline int my_min(int x,int y) {return x<y ? x:y;}
123 inline int Read()
124 {
125     int sum=0;
126     char ch=getchar();
127     while (ch<0||ch>9) ch=getchar();
128     while (ch>=0&&ch<=9) 
129     {
130         sum=sum*10+ch-0;
131         ch=getchar();
132     }
133     return sum;
134 }

 

[USACO 13DEC]Vacation Planning(gold)

标签:numbers   关键点   mini   live   current   panel   most   getchar   getch   

原文地址:http://www.cnblogs.com/NaVi-Awson/p/7364859.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!