6
17
2015
0

bzoj 4144: [AMPPZ2014]Petrol

就是一结论题目

首先如果所有点都是加油站,那么把询问离线维护可达的生成森林就OK了

现在有些点不是加油站

我们预处理出每个不是加油站的点距离最近的加油站,就变成了一个蜘蛛网的结构(其实是一个树)

然后我们对于原来的每条边对应这两个加油站之间的边如果原来有一条(x,y,d)的边,记bel[x]表示距离x最近的加油站,d[x]表示距离x最近的加油站的距离,那么这样一条边对应着(bel[x],bel[y],d+d[x]+d[y])这样一个点,然后问题就解决了

证明:

我还是大体证明了以下这个结论(其实就一个拟阵)

//coder : davidwang
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <bitset>
#include <deque>
using namespace std;
#define LL long long
#define X first
#define Y second
template<typename T>
inline T sqr(const T &x){ return x*x; }
inline int read()
{
	int ret=0,f=1; char ch;
	for (ch=getchar();ch<'0' || ch>'9';ch=getchar())
		if (ch=='-') f=-f;
	for (;'0'<=ch && ch<='9';ch=getchar())
		ret=ret*10+ch-'0';
	return ret*f;
}
const int N = 200010;
const LL inf = 1LL<<60;
struct edge{
	int x,y,l,pos;
	edge(int x=0,int y=0,int l=0,int pos=0): x(x),y(y),l(l),pos(pos){}
	int operator<(const edge &A) const{
		return l<A.l || (l==A.l && pos<A.pos);
	}
}e[N*4];
vector<pair<int,int> >g[N];
vector<pair<int,int> >::iterator it;
int q[N+2],bel[N],ans[N],in[N];
LL d[N];
inline int next(int &x){ x=(x%N+1); return x;}
struct UnionFindSet{
	int Set[N],Size[N];
	inline void init(int n){
		for (int i=1;i<=n;i++){
			Set[i]=i;
			Size[i]=1;
		}
	}
	int find(int x){
		if (Set[x]==x) return x;
		Set[x]=find(Set[x]);
		return Set[x];
	}
	inline int join(int x,int y){
		x=find(x),y=find(y);
		if (x==y) return 0;
		if (Size[x]>Size[y]) swap(x,y);
		Set[x]=y; Size[y]+=Size[x];
		return 1;
	}
}s;
int n,m,T,cnt,E;
int main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	n=read(); m=read(); E=read();
	for (int i=1;i<=n;i++) d[i]=inf;
	for (int i=1;i<=m;i++){
		int x=read();
		bel[x]=x;
		d[x]=0;
		in[x]=1;
		q[i]=x;
	}
	for (int i=1;i<=E;i++){
		int x=read(),y=read(),z=read();
		g[x].push_back(make_pair(y,z));
		g[y].push_back(make_pair(x,z));
	}
	int head=0,tail=m;
	while (head!=tail){
		int u=q[next(head)];
		for (it=g[u].begin();it!=g[u].end();it++){
			if (d[it->X]>d[u]+it->Y){
				d[it->X]=d[u]+it->Y;
				bel[it->X]=bel[u];
				if (!in[it->X]){
					q[next(tail)]=it->X;
					in[it->X]=1;
				}
			}
		}
		in[u]=0;
	}
	for (int i=1;i<=n;i++)
		for (it=g[i].begin();it!=g[i].end();it++)
			if (bel[it->X] != bel[i]){
				LL now=d[i]+d[it->X]+it->Y;
				if (now>2e9) continue;
				e[++cnt]=edge(bel[i],bel[it->X],(int)now);
			}
	T=read();
	for (int i=1;i<=T;i++){
		cnt++;
		e[cnt].x=read(); e[cnt].y=read();
		e[cnt].l=read();
		e[cnt].pos=i;
	}
	sort(e+1,e+cnt+1);
	s.init(n);
	for (int i=1;i<=cnt;i++){
		if (e[i].pos==0)
			s.join(e[i].x,e[i].y);
		else
			ans[e[i].pos]=s.find(e[i].x)==s.find(e[i].y);
	}
	for (int i=1;i<=T;i++) printf("%s\n",ans[i]?"TAK":"NIE");
	return 0;
}

 

Category: 未分类 | Tags: bzoj 并查集 拟阵 | Read Count: 1084

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com