zoukankan      html  css  js  c++  java
  • [USACO 13DEC]Vacation Planning(gold)

    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
    %d
    ",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 }
  • 相关阅读:
    30行js让你的rem弹性布局适配所有分辨率(含竖屏适配)(转载)
    JavaScript事件流原理解析
    Java中this和super的用法和区别
    Java多态面试题案例几解题思路
    Java多态的向上转型和向下转型
    Java方法的重载和重写
    Java冒泡具体的原理,以及下标的变化
    Java中的冒泡排序和选择排序
    使用Java实现对一个数组的增删改查以及初始化
    Java中构造函数传参数在基本数据类型和引用类型之间的区别
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7364859.html
Copyright © 2011-2022 走看看