2017 Multi-University Training Contest 9 && HDU 6166 Senior Pan 【最短路+思维】
来源:互联网 发布:淘宝商城入驻 编辑:程序博客网 时间:2024/05/21 10:13
Senior Pan
Time Limit: 12000/6000 MS (Java/Others) Memory Limit:131072/131072 K (Java/Others)
Total Submission(s): 468 Accepted Submission(s): 163
Problem Description
SeniorPan fails in his discrete math exam again. So he asks Master ZKC to give himgraph theory problems everyday.
The task is simple : ZKC will give Pan a directed graph every time, and selectssome nodes from that graph, you can calculate the minimum distance of everypair of nodes chosen in these nodes and now ZKC only cares about the minimumamong 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 TestCases.1≤T≤5.Then T Test Cases, for each Test Cases, the first line contains twointegers n,m representing the number of nodes and the number ofedges.1≤n,m≤100000
Then m lines follow. Each line contains three integers xi,yi representing anedge, andvi representing its length.1≤xi,yi≤n,1≤vi≤100000
Then one line contains one integer K, the number of nodes that Master Dongselects out.1≤K≤n
The following line contains K unique integers ai, the nodes thatMaster 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
【题意】
给出一个n个点,m条边的有向图,从这n个点中选出k个,现在我们需要从这k个点中选出一个点作为起点,一个点作为终点,使得从起点到终点的距离是所有选择中最小的。
【思路】
显然,我们需要考虑这k个点两两之间的距离,取最小值,但这样做时间不允许,我们考虑优化。
我们可以把这k个点分成两个集合,一个集合作为起点,一个集合作为终点,那么我们要求的便转化为了多起点多终点的最短路,这只需要建立一个超级源点和超级汇点,然后跑一遍最短路即可。
但现在问题是该如何把k个点分成两个集合,使得所有情况都不被遗漏呢?(如果随意分的话,也许原来是最优解的两个点被分到了同一集合,显然结果就不对了)
我们考虑对这k个点的编号进行二进制分解。
首先有一个显然的结论:任意两个不同的数,它们的二进制数总有一位是不同的。
那只要我们枚举每一个二进制位,根据该位是否为1,分成两个集合,根据这个结论,总会有一种分法使某两个点不在同一集合内。
由于只要跑2*logn次最短路,时间复杂度为O(2*nlognlogn)。
(据说还可以用随机化分集合,分得越多出错概率越小,分个二三十次就能得到正解。。。)
#include <cstdio>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn = 100005;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-9;int n,m,k,cnt,Max;int a[maxn];int dis[maxn];int color[maxn];bool vis[maxn];int head[maxn];struct point{ int u,v,w;}p[maxn];struct node{ int v,w,next;}e[maxn];void add(int u,int v,int w){ e[cnt].v=v; e[cnt].w=w; e[cnt].next=head[u]; head[u]=cnt++;}void build() //建图{ cnt=0; mst(head,-1); for(int i=0;i<m;i++) { int u=color[p[i].u]; int v=color[p[i].v]; add(u,v,p[i].w); }}int spfa(int s,int t){ mst(dis,0x3f); mst(vis,0); queue<int>q; q.push(s); dis[s]=0; vis[s]=1; while(q.size()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];~i;i=e[i].next) { int v=e[i].v; int w=e[i].w; if(w+dis[u]<dis[v]) { dis[v]=dis[u]+w; if(vis[v]==0) { vis[v]=1; q.push(v); } } } } return dis[t];}int solve(){ for(int i=0;i<=n+1;i++) { color[i]=i; } int ss=0,tt=n+1; //建立超级源点,超级汇点 int ans=INF; for(int i=0;(1<<i)<=Max;i++) //枚举二进制位 { for(int j=0;j<k;j++) //把k个点分成两个集合 { if((a[j]>>i)&1) color[a[j]]=ss; else color[a[j]]=tt; } build(); ans=min(ans,spfa(ss,tt)); //由于都是有向边,所以需要正向反向跑两次 ans=min(ans,spfa(tt,ss)); } return ans;}int main(){ int cas=1; rush() { scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d%d",&p[i].u,&p[i].v,&p[i].w); } scanf("%d",&k); Max=0; for(int i=0;i<k;i++) { scanf("%d",&a[i]); Max=max(Max,a[i]); } int ans=solve(); printf("Case #%d: %d\n",cas++,ans); } return 0;}
- 2017 Multi-University Training Contest 9 && HDU 6166 Senior Pan 【最短路+思维】
- 2017 Multi-University Training Contest 9 1006 Senior Pan spfa
- Hdu 6166 Senior Pan【思维+随机化+最短路】好题~
- HDU 6166 Senior Pan(思维 最短路)
- 2017 Multi-University Training Contest 10 1011 Two Paths HDU 6181 (次短路+最短路数量)
- hdu 6166 Senior Pan 最短路
- hdu 6166 Senior Pan(最短路)
- HDU 6166 Senior Pan (思维枚举+最短路 求最近点对)
- hdu 5294 - Tricks Device(2015 Multi-University Training Contest 1 )最短路+网络流
- HDU 3068 2017 Multi-University Training Contest
- HDU 6034 & 2017 Multi-University Training Contest
- hdu 6034 2017 Multi-University Training Contest
- HDU 3065 2017 Multi-University Training Contest
- HDU 6047 2017 Multi-University Training Contest
- HDU 6052 2017 Multi-University Training Contest
- HDU 6058 2017 Multi-University Training Contest
- HDU 6078 2017 Multi-University Training Contest
- HDU 6166 Senior Pan (最短路 好题)
- std::lock的使用方法
- Java实现指定数据表导出生成Excel
- ACS服务器搭建步骤
- 手机端微信传动文件,超出文件限制,怎么办?
- 发送取短信验证码
- 2017 Multi-University Training Contest 9 && HDU 6166 Senior Pan 【最短路+思维】
- hdu1231最大连续子序列dp
- mvvm原理代码
- Codeforces 834D The Bakery【Dp+线段树】
- Python第三方库——xlrd&xlwt读写Excel表
- HBase(2.1)-HBase介绍
- 数组和链表、栈和队列
- git.oschina.net提交文档方法
- 《机器学习实战》学习笔记3