Meeting HDU - 5521

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Meeting HDU - 5521相关的知识,希望对你有一定的参考价值。

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的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5521.Meeting 最短路模板题

HDU 5521 Meeting(虚拟节点+最短路)

hdu 5521 Meeting(最短路)

HDU 5521 Meeting 最短路

HDU - 5521 Meeting

Meeting HDU - 5521