hdu 6166 Senior Pan

地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6166

题目:

Senior Pan

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 245    Accepted Submission(s): 71

Problem Description

Senior Pan fails in his discrete math exam again. So he asks Master ZKC to give him graph theory problems everyday.
The task is simple : ZKC will give Pan a directed graph every time, and selects some nodes from that graph, you can calculate the minimum distance of every pair of nodes chosen in these nodes and now ZKC only cares about the minimum among them. That is still too hard for poor Pan, so he asks you for help.

Input

The first line contains one integer T, represents the number of Test Cases.1≤T≤5.Then T Test Cases, for each Test Cases, the first line contains two integers n,m representing the number of nodes and the number of edges.1≤n,m≤100000
Then m lines follow. Each line contains three integers xi,yi representing an edge, and vi representing its length.1≤xi,yi≤n,1≤vi≤100000
Then one line contains one integer K, the number of nodes that Master Dong selects out.1≤K≤n
The following line contains K unique integers ai, the nodes that Master Dong selects out.1≤ai≤n,ai!=aj

Output

For every Test Case, output one integer: the answer

Sample Input

1
5 6
1 2 1
2 3 3
3 1 3
2 5 1
2 4 2
4 3 1
3
1 3 5

Sample Output

Case #1: 2

Source

2017 Multi-University Training Contest - Team 9

思路:

  官方题解看的有点迷,看了半天才懂。

  就是把k个关键点分为两个点集st,se,两个点集间的最短距离可以通过两次dijkstra或者spfa求出来。

  所以现在的关键问题是怎么划分点集,使得任意点对都会被划分到不同点集中。

  一次划分显然是不可能的,所以可进行有限次划分满足上面的要求。

  考虑到任意不同数对x,y。x,y在二进制下必有一位不相同。

  所以可以通过二进制位进行20次划分,这样就可以覆盖所有情况。

  同时还有一种随机做法,就是进行t次random_shuffle用来划分点集。

 1 #include <bits/stdc++.h>
 2
 3 using namespace std;
 4
 5 #define MP make_pair
 6 #define PB push_back
 7 typedef long long LL;
 8 typedef pair<int,int> PII;
 9 const double eps=1e-8;
10 const double pi=acos(-1.0);
11 const int K=1e5+7;
12 const int mod=1e9+7;
13
14 vector<PII >mp[K];
15 vector<int>key,st,se;
16 LL dis[K];
17 int n,m,k;
18
19 LL spfa(vector<int> &s,vector<int> &e)
20 {
21     queue<int>q;
22     fill(dis+1,dis+n+1,1e12);
23     for(auto &x:s)
24         q.push(x),dis[x]=0;
25     while(q.size())
26     {
27         int u=q.front();q.pop();
28         for(auto &v:mp[u])
29         if(dis[v.first]>dis[u]+v.second)
30         {
31             dis[v.first]=dis[u]+v.second;
32             q.push(v.first);
33         }
34     }
35     LL ret=1e15;
36     for(auto &x:e)
37         ret=min(ret,dis[x]);
38     return ret;
39 }
40 int main(void)
41 {
42     //freopen("in.acm","r",stdin);
43     int t,cs=1;cin>>t;
44     while(t--)
45     {
46         memset(mp,0,sizeof mp);
47         key.clear();
48         LL ans=1e15;
49         scanf("%d%d",&n,&m);
50         for(int i=1,x,y,z;i<=m;i++)
51             scanf("%d%d%d",&x,&y,&z),mp[x].PB(MP(y,z));
52         scanf("%d",&k);
53         for(int i=1,x;i<=k;i++)
54             scanf("%d",&x),key.PB(x);
55         for(int i=0;i<=20;i++)
56         {
57             st.clear(),se.clear();
58             for(auto &x:key)
59             if(x&(1<<i))
60                 st.push_back(x);
61             else
62                 se.push_back(x);
63             ans=min(ans,min(spfa(st,se),spfa(se,st)));
64         }
65         printf("Case #%d: %lld\n",cs++,ans);
66     }
67     return 0;
68 }
时间: 2024-10-12 12:49:46

hdu 6166 Senior Pan的相关文章

2017多校第9场 HDU 6166 Senior Pan 堆优化Dij

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6166 题意:给你一个有向图,然后给你k个点,求其中一个点到另一个点的距离的最小值. 解法:枚举二进制位按照标号当前位为1 和当前位为0分为两个集合,每次求解两个集合之间的最短路即可覆盖到所有的点对.时间复杂度20*dijstla时间,这样做的正确性在哪?显然我们需要的答案至少有一个二进制位不同,那么这样求解肯定可以找到正确答案,事实上还可以随机分组emmmm... #include <bits/st

HDU 6166 Senior Pan(多校第九场 二进制分组最短路)

题意:给出n个点和m条有向边(有向边!!!!我还以为是无向查了半天),然后给出K个点,问这k个点中最近的两点的距离 思路:比赛时以为有询问,就直接丢了,然后这题感觉思路很棒,加入把所有点分成起点和终点两部分,然后加个S点和T点与他们 的距离为0,然后跑最短路就可以了,但是这样有可能最近的两个点都在起点或者都在终点,那么就不一定是最短的,所以就有个二进制分组. 考虑每个点的编号的二进制表示,那么对于任何两个点,他们至少有一位二进制不同,那么我们通过枚举二进制的位,当前位为1的作为起点集合, 当前位

hdu 5280 Senior&#39;s Array

题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5280 Senior's Array Description One day, Xuejiejie gets an array $A$. Among all non-empty intervals of $A$, she wants to find the most beautiful one. She defines the beauty as the sum of the interval. Th

hdu 5281 Senior&#39;s Gun

题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5281 Senior's Gun Description Xuejiejie is a beautiful and charming sharpshooter. She often carries $n$ guns, and every gun has an attack power $a[i]$. One day, Xuejiejie goes outside and comes across $m

HDU #5283 Senior&#39;s Fish

题目描述: 平面上有一些鱼,初始时鱼会在一些位置,某些时刻编号在一段区间内的鱼会同时向x轴正方向,或y轴正方向平移一定距离,某些时刻会询问一个矩形内鱼的数量. 解题思路: 显然地,求一个矩形内的鱼可以用矩形四个顶点为右上角的整个左下矩形加加减减.那么问题就转化为一个顶点左下角矩形内鱼的数量.注意到鱼只会向右和向上的话,那就很好做.维护两颗线段树,分别维护编号在l~r的鱼的x坐标最大值.y坐标最大值.每次修改对应区间加.每次如果区间最大值大于限制,那就找出最大值的位置,赋为-inf,同时在树状数组

hdu 5280 Senior&#39;s Array(最大子段和)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5280 题意:将一个长度为n的数组,将里面某一个数改为p,使改变后最大子段和最大. 题解:dp[i]=max(dp[i-1)+a[i],a[i]),表示以第 i 个数结束的最大子段和,时间复杂度为O(n). 1)由于n<=1000,可以暴力解决,将每一个数都依次改为p,求出最大的子段和,再去这些最大子段和中最大的,时间复杂度为O(n*n); #include <iostream> #inclu

HDU 5280 Senior&#39;s Array (暴力,水)

题意:给一个数列,再给一个数字p,要求p一定要替换掉数列中的一个元素,然后求最大连续子序列之和. 思路:1000*1000的复杂度,O(n*n) .就是每个都试,然后求和. 1 #include <bits/stdc++.h> 2 #define LL long long 3 #define pii pair<int,int> 4 #define INF 0x7f7f7f7f 5 using namespace std; 6 const int N=2000; 7 int a[N]

[最大子序列和]Hdu 5280 Senior&#39;s Array

题意:一个序列,在其中一个数必须替换成给定数字p的条件下,求最大连续子序列之和. 依次把每一个数替换成p,求每次的最大连续和,找出最大值.O(n^2). #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> typedef long long ll; using namespace std; const int MAXN=1000+5; const int

HDU 5281 Senior&amp;#39;s Gun 杀怪

题意:给出n把枪和m个怪.每把枪有一个攻击力,每一个怪有一个防御力.假设某把枪的攻击力不小于某个怪的防御力则能将怪秒杀,否则无法杀死.一把枪最多仅仅能杀一个怪,不能用多把枪杀同一个怪.每杀一次怪能够得到枪的攻击力减去怪的防御力的的分数. 求得分的最大值. 贪心.首先我们考虑这样一种情况:用攻击力为A的枪杀防御力为a的怪,攻击力为B的枪杀防御力为b的怪.则得分为A - a + B - b. 最好还是设A ≤ B,则有a ≤ A ≤ B.b ≤ B.假设有A < b,那么我们考虑用B杀a.而不使用A