Meeting HDU - 5521
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Meeting HDU - 5521相关的知识,希望对你有一定的参考价值。
题意:
一共有n个点,有m个块,每个块内有Si个点,块内点彼此到达费用为wi,两个人分别位于1和n号块,两者同时出发问最短时间遇到是多少?在哪些地方可以遇到?
ΣSi<=106
题解:
题意很明确,我们需要先建边,然后从点1开始跑最短路得到dis[i],再从点n跑最短路得到dist[i]
dis[i]表示第1个点到第i个点的最短距离
dist[i]表示第n个点到第i个点的最短距离
答案就是minn= min(max(dis[i],dist[i]),minn)
因为两者同时出发,所以时间取长者,然后找最短时间所以取min
题目难度在于ΣSi<=106,如果你按照块内所有点两两建边,那复杂度肯定暴力。(考虑极端情况所有点在一个块内),那怎么解决?我们可以在块外建议一个新点x,让块内所有点与其相连,边权不变,这样任意两个点都可以通过这个x中间点实现连接,这样就巧妙建边(会网络流的应该好理解,相当于一个人造源点)
建议不要用ios::sync_with_stdio(0);玄学错误,导致我wa了八次
代码:
#include <bits/stdc++.h>
using namespace std;
#define asd cout<<" SB "<<endl;
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
const int maxn=1e6+9;
struct node{
int v;
int c;
node(int v=0,int c=0):v(v),c(c){
}
bool operator<(const node &r)const{
return c>r.c;
}
};
struct cmp{
int x;
cmp(int x=0):x(x){
}
bool operator<(const cmp &r)const{
return x>r.x;
}
};
struct Edge{
int v,cost;
Edge(int _v=0,int _cost=0):v(_v),cost(_cost){
}
};
vector<Edge>E[maxn];
bool vis[maxn];
int dist[maxn];
int dis[maxn];
void dij(int n,int start){
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)dist[i]=INF;
priority_queue<node>q;
while(!q.empty())q.pop();
dist[start]=0;
q.push(node(start,0));
node tmp;
while(!q.empty()){
tmp=q.top();
q.pop();
int u=tmp.v;
if(vis[u])continue;
vis[u]=1;
for(int i=0;i<E[u].size();i++){
int v=E[tmp.v][i].v;
int cost=E[u][i].cost;
if(!vis[v]&&dist[v]>dist[u]+cost){
dist[v]=dist[u]+cost;
q.push(node(v,dist[v]));
}
}
}
}
int main(){
ios::sync_with_stdio(0);
int t;
cin>>t;
int cas=0;
while(t--){
memset(E,0,sizeof(E));
int n,m;
cin>>n>>m;
// for(int i=1;i<=n;i++)dis[i]=INF;
int tot=0;
for(int i=1;i<=m;i++){
int w;
cin>>w;
int S;
cin>>S;
for(int j=1;j<=S;j++){
int x;
cin>>x;
// printf("u=%d v=%d w=%d\\n",n+i,x,w);
E[n+i].push_back(Edge(x,w));
E[x].push_back(Edge(n+i,w));
}
}
// for(int i=n+1;i<=n+m;i++){
// for(int j=i+1;j<=n+m;j++){
// printf("u=%d v=%d w=%d\\n",i,j,0);
// E[i].push_back(Edge(j,0));
// E[j].push_back(Edge(i,0));
// }
// }
dij(n+m,1);
for(int i=1;i<=n;i++)dis[i]=dist[i];
dij(n+m,n);
int minn=INF;
for(int i=1;i<=n;i++)
minn=min(minn,max(dis[i],dist[i]));
if(minn==INF)
{
printf("Case #%d: Evil John\\n",++cas);
continue;
}
priority_queue<cmp>q;
for(int i=1;i<=n;i++){
if(max(dis[i],dist[i])==minn){
q.push(i);
}
}
bool f=0;
printf("Case #%d: %d\\n",++cas,minn/2);
while(!q.empty()){
if(f==0)printf("%d",q.top().x);
else printf(" %d",q.top().x);
q.pop();
f=1;
}
printf("\\n");
}
return 0;
}
/*
2
5 4
1 3 1 2 3
2 2 3 4
3 2 1 5
3 3 3 4 5
3 1
1 2 1 2
*/
以上是关于Meeting HDU - 5521的主要内容,如果未能解决你的问题,请参考以下文章