题解 [SDOI2010]所驼门王的宝藏

Posted 欢迎,Administrator-09

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 [SDOI2010]所驼门王的宝藏相关的知识,希望对你有一定的参考价值。

传送门

保分题再度爆零,自闭ing×2
tarjan没写vis数组,点权算的也有点问题
这题情况3的连边有点麻烦,考场上想了暴力想了二分就是没想到可以直接拿map水过去
不过map果然贼慢,所以这也是一个哈希表的板子题

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long 
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long 

inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c==\'-\') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

struct hush_map{
	static const int SIZE=100010;
	struct node{pair<int, int> p; int dat, next;}e[SIZE<<1];
	int head[SIZE], size;
	hush_map():size(0){memset(e, 0, sizeof(e));}
	inline int operator [] (pair<int, int> p) {
		ll t = 1ll*p.first*p.second%SIZE;
		for (int i=head[t]; i; i=e[i].next) {
			if (e[i].p==p) return e[i].dat;
		}
		return 0;
	}
	inline void add(pair<int, int> p, int dat) {
		ll t = 1ll*p.first*p.second%SIZE;
		node *k=&e[++size];
		k->p=p; k->dat=dat; k->next=head[t];
		head[t] = size;
	}
};

struct edge{int from, to, next;}e[N*60]; // 乱开的大小
int r, c, n;
int head[N], size=1, cnt[N], val[N];
int dfn[N], low[N], siz, s[N], top, fa[N], h[N], tot[N];
bool vis[N];
//unsigned short mp[5005][5005];
//map<pair<int,int>, int> mp;
hush_map mp;
const int dir[][2] = {{-1,1},{-1,0},{-1,-1},{0,1},{0,-1},{1,1},{1,0},{1,-1}};
struct point{int x, y, k, rank; inline void build(int i){x=read(); y=read(); k=read(); mp.add(pair<int, int>(x, y), i); rank=i;}}p[N];

inline bool cmpx(point a, point b) {return a.x==b.x?a.y<b.y:a.x<b.x;}
inline bool cmpy(point a, point b) {return a.y==b.y?a.x<b.x:a.y<b.y;}
inline void add(int s, int t) {edge *k=&e[++size]; k->from=s; k->to=t; k->next=head[s]; head[s]=size;}
inline void add2(int s, int t) {edge *k=&e[++size]; k->from=s; k->to=t; k->next=h[s]; h[s]=size;}
inline int find(int u) {return fa[u]==u?u:fa[u]=find(fa[u]);}

void tarjan(int u) {
	//cout<<"tarjan "<<u<<endl;
	dfn[u]=low[u]=++siz;
	s[++top] = u;
	vis[u] = 1;
	for (int i=head[u],v; i; i=e[i].next) {
		v = e[i].to;
		if (!dfn[v]) {
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if (vis[v]) low[u] = min(low[u], low[v]);
	}
	if (dfn[u] == low[u]) {
		//cout<<"node"<<endl;
		int t=find(u), f;
		while (s[top]!=u) {
			f = find(s[top]);
			vis[s[top]]=0;
			cnt[t] += cnt[f];
			fa[s[top--]] = t;
		}
		--top;
		vis[u] = 0;
	}
}

signed main()
{
	#ifdef DEBUG
	freopen("1.in", "r", stdin);
	#endif
	
	//cout<<double(sizeof(head)*9+sizeof(mp)+sizeof(e)+sizeof(p))/1024/1024<<endl;
	
	n=read(); r=read(); c=read();
	for (int i=1; i<=n; ++i) p[i].build(i), val[i]=1;
	for (int i=1; i<=n; ++i) fa[i]=i, cnt[i]=1;
	sort(p+1, p+n+1, cmpx);
	for (int i=1,keypoint; i<=n; ++i) {
		if (i==0 || p[i].x!=p[i-1].x) keypoint=0;
		if (p[i].k==1) {
			if (keypoint) add(p[i].rank, keypoint);
			else {
				for (int j=i-1; j&&p[j].x==p[i].x; --j) add(p[i].rank, p[j].rank);
				for (int j=i+1; j<=n&&p[j].x==p[i].x; ++j) add(p[i].rank, p[j].rank);
				keypoint = p[i].rank;
			}
		}
	}
	sort(p+1, p+n+1, cmpy);
	for (int i=1,keypoint; i<=n; ++i) {
		if (i==0 || p[i].y!=p[i-1].y) keypoint=0;
		if (p[i].k==2) {
			if (keypoint) add(p[i].rank, keypoint);
			else {
				for (int j=i-1; j&&p[j].y==p[i].y; --j) add(p[i].rank, p[j].rank);
				for (int j=i+1; j<=n&&p[j].y==p[i].y; ++j) add(p[i].rank, p[j].rank);
				keypoint = p[i].rank;
			}
		}
	}
	#if 0
	for (int i=1; i<=n; ++i) 
		if (p[i].k==3) {
			int x=p[i].x, y=p[i].y, r=p[i].rank, t;
			for (int j=0; j<8; ++j) {
				t = mp[x+dir[j][0]][y+dir[j][1]];
				if (t) add(r, t);
			}
		}
	#else
	for (int i=1; i<=n; ++i) 
		if (p[i].k==3) {
			int x=p[i].x, y=p[i].y, r=p[i].rank, t;
			for (int j=0; j<8; ++j) {
				t = mp[pair<int,int>(x+dir[j][0], y+dir[j][1])];
				if (t) add(r, t);
			}
		}
	#endif
	for (int i=1; i<=n; ++i) if (!dfn[i]) tarjan(i);
	memset(vis, 0, sizeof(vis));
	//for (int i=1; i<=n; ++i) cout<<find(i)<<endl;
	//cout<<"dfn "; for (int i=1; i<=n; ++i) cout<<dfn[i]<<\' \'; cout<<endl;
	//cout<<"low "; for (int i=1; i<=n; ++i) cout<<low[i]<<\' \'; cout<<endl;
	//cout<<"cnt "; for (int i=1; i<=n; ++i) cout<<cnt[i]<<\' \'; cout<<endl;
	int lim=size;
	for (int i=1,f1,f2; i<=lim; ++i) {
		f1=find(e[i].from); f2=find(e[i].to);
		vis[f1]=1; vis[f2]=1;
		if (f1 != f2) {
			add2(f1, f2); ++tot[f2];
		}
	}
	//cout<<"vis "; for (int i=1; i<=n; ++i) cout<<vis[i]<<\' \'; cout<<endl;
	
	queue<int> q;
	for (int i=1; i<=n; ++i) if (!tot[i] && vis[i]) q.push(i), val[i]=cnt[i]; //, cout<<"push "<<i<<endl;
	
	while (!q.empty()) {
		int u=q.front(); q.pop();
		for (int i=h[u],v; i; i=e[i].next) {
			v = e[i].to;
			val[v] = max(val[v], val[u]+cnt[v]); //, cout<<" -> "<<u<<\' \'<<v<<"  "<<val[v]<<\' \'<<(val[u]+cnt[v])<<endl;
			//assert(find(v)!=find(u));
			if (--tot[v]==0) q.push(v);
		}
	}
	//cout<<"cnt "; for (int i=1; i<=n; ++i) cout<<cnt[i]<<\' \'; cout<<endl;
	
	int ans=1;
	for (int i=1; i<=n; ++i) if (vis[i]) ans=max(ans, val[i]);
	printf("%d\\n", ans);
	
	return 0;
}

以上是关于题解 [SDOI2010]所驼门王的宝藏的主要内容,如果未能解决你的问题,请参考以下文章

题解 [SDOI2010]所驼门王的宝藏

SDOI2010所驼门王的宝藏

[SDOI2010] 所驼门王的宝藏

BZOJ:1924: [Sdoi2010]所驼门王的宝藏

bzoj 1924: [Sdoi2010]所驼门王的宝藏

[SDOI2010] 所驼门王的宝藏