• 【BZOJ1924】【SDOI2010】所驼门王的宝藏(Tarjan,SPFA)


    题目描述

    在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族。被族人恭称为“先知”的Alpaca L. Sotomon是这个家族的领袖,外人也称其为“所驼门王”。所驼门王毕生致力于维护家族的安定与和谐,他曾亲自率军粉碎河蟹帝国主义的野蛮侵略,为族人立下赫赫战功。所驼门王一生财宝无数,但因其生性节俭低调,他将财宝埋藏在自己设计的地下宫殿里,这也是今天Henry Curtis故事的起点。Henry是一个爱财如命的贪婪家伙,而又非常聪明,他费尽心机谋划了这次盗窃行动,破解重重机关后来到这座地下宫殿前。

    整座宫殿呈矩阵状,由R×C间矩形宫室组成,其中有N间宫室里埋藏着宝藏,称作藏宝宫室。宫殿里外、相邻宫室间都由坚硬的实体墙阻隔,由一间宫室到达另一间只能通过所驼门王独创的移动方式——传送门。所驼门王为这N间藏宝宫室每间都架设了一扇传送门,没有宝藏的宫室不设传送门,所有的宫室传送门分为三种:

    “横天门”:由该门可以传送到同行的任一宫室;
    
    “纵寰门”:由该门可以传送到同列的任一宫室;
    “自*河蟹*由*河蟹*门”:由该门可以传送到以该门所在宫室为中心周围8格中任一宫室(如果目标宫室存在的话)。
    

    深谋远虑的Henry当然事先就搞到了所驼门王当年的宫殿招标册,书册上详细记录了每扇传送门所属宫室及类型。而且,虽然宫殿内外相隔,但他自行准备了一种便携式传送门,可将自己传送到殿内任意一间宫室开始寻宝,并在任意一间宫室结束后传送出宫。整座宫殿只许进出一次,且便携门无法进行宫室之间的传送。不过好在宫室内传送门的使用没有次数限制,每间宫室也可以多次出入。

    现在Henry已经打开了便携门,即将选择一间宫室进入。为得到尽多宝藏,他希望安排一条路线,使走过的不同藏宝宫室尽可能多。请你告诉Henry这条路线最多行经不同藏宝宫室的数目。
    输入输出格式
    输入格式:

    输入文件sotomon.in

    第一行给出三个正整数N, R, C。

    以下N行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第xi行第yi列的藏宝宫室,类型为Ti。Ti是一个1~3间的整数,1表示可以传送到第xi行任意一列的“横天门”,2表示可以传送到任意一行第yi列的“纵寰门”,3表示可以传送到周围8格宫室的“自河蟹河蟹门”。

    保证1≤xi≤R,1≤yi≤C,所有的传送门位置互不相同。

    输出格式:

    输出文件sotomon.out只有一个正整数,表示你确定的路线所经过不同藏宝宫室的最大数目。

    输入样例#1:

    10 7 7
    2 2 1
    2 4 2
    1 7 2
    2 7 3
    4 2 2
    4 4 1
    6 7 3
    7 7 1
    7 5 2
    5 2 1

    输出样例#1:

    9

    题解

    和洛谷的缩点模板题简直不要一样。。。。
    首先考虑建边,我暴力建边然后就过了???
    用vector存一下每一行每一列的点
    然后map储存一下点的位置
    对于每一种门,暴力连上边
    恩,解决完了连边
    剩下的很简单啦
    Tarjan缩点
    然后重新连边
    用一个虚拟点作为源点
    跑SPFA最长路就可以啦

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAX 110000
    #define MAXL 5000050
    #define INF 1000000000
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    struct Node
    {
    	int x,y;
    };
    inline bool operator <(Node a,Node b)
    {
    	if(a.x!=b.x)
    		return a.x<b.x;
    	else return a.y<b.y;
    }
    struct Line
    {
    	int v,next;
    }e[MAXL];
    struct Line2
    {
    	int v,next,w;
    }ee[MAXL];
    int H[MAX],cnt2=1;
    inline void Add(int u,int v,int w)
    {
    	ee[cnt2]=(Line2){v,H[u],w};
    	H[u]=cnt2++;
    }
    int N,M;
    int h[MAX],cnt=1;
    int w[MAX],dis[MAX],ans;
    int xx[MAX],yy[MAX],tt[MAX];
    inline void Add(int u,int v)
    {
    	e[cnt]=(Line){v,h[u]};
    	h[u]=cnt++;
    }
    int tim,S[MAX],top;
    bool vis[MAX];
    int W[MAX],G[MAX];
    int dfn[MAX],low[MAX],group;
    vector<int> X[MAX],Y[MAX];
    map<Node,int> qt;
    int d[8][2]={1,0,0,1,-1,0,0,-1,1,1,1,-1,-1,1,-1,-1};
    void Tarjan(int u)
    {
    	dfn[u]=low[u]=++tim;
    	vis[u]=true;S[++top]=u;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		if(!dfn[v])
    		{
    			Tarjan(v);
    			low[u]=min(low[u],low[v]);
    		}
    		else
    			if(vis[v])
    				low[u]=min(low[u],dfn[v]);
    	}
    	if(low[u]==dfn[u])
    	{
    		++group;
    		int v;
    		do
    		{
    			v=S[top--];
    			W[group]++;
    			G[v]=group;
    			vis[v]=false;
    		}while(v!=u);
    	}
    }
    int main()
    {
    	N=read();read();read();
    	for(int i=1;i<=N;++i)
    	{
    		xx[i]=read();yy[i]=read();tt[i]=read();
    		X[xx[i]].push_back(i);Y[yy[i]].push_back(i);
    		qt[(Node){xx[i],yy[i]}]=i;
    	}
    	for(int i=1;i<=N;++i)
    	{
    		if(tt[i]==1)
    		{
    			for(int j=0,l=X[xx[i]].size();j<l;++j)
    				Add(i,X[xx[i]][j]);
    		}
    		else if(tt[i]==2)
    		{
    			for(int j=0,l=Y[yy[i]].size();j<l;++j)
    				Add(i,Y[yy[i]][j]);
    		}
    		else
    		{
    			for(int j=0;j<8;++j)
    			{
    				int xxx=xx[i]+d[j][0];
    				int yyy=yy[i]+d[j][1];
    				Node uuu=(Node){xxx,yyy};
    				if(qt.find(uuu)!=qt.end())
    					Add(i,qt[uuu]);
    			}
    		}
    	}
    	for(int i=1;i<=N;++i)
    		if(!dfn[i])
    			Tarjan(i);
    	for(int u=1;u<=N;++u)
    	{
    		for(int i=h[u];i;i=e[i].next)
    		{
    			int v=e[i].v;
    			if(G[u]!=G[v])
    				Add(G[u],G[v],W[G[v]]);
    		}
    	}
    	for(int i=1;i<=group;++i)Add(0,i,W[i]);
    	queue<int> Q;while(!Q.empty())Q.pop();
    	int ans=0;
    	memset(vis,0,sizeof(vis));
    	Q.push(0);vis[0]=true;
    	while(!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for(int i=H[u];i;i=ee[i].next)
    		{
    			int v=ee[i].v,w=ee[i].w;
    			if(dis[v]<dis[u]+w)
    			{
    				dis[v]=dis[u]+w;
    				ans=max(ans,dis[v]);
    				if(!vis[v])
    				{
    					vis[v]=true;
    					Q.push(v);
    				}
    			}
    		}
    		vis[u]=false;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    PhpPresentation ppt 导出PPT
    Springcloudalibaba学习实践(1) nacos环境搭建&Eureka Server搭建
    Springcloudalibaba学习实践(2) nacos&Eureka Server服务注册实践
    xna 3.1 to xna 4.0 conversion cheat sheet.(转)
    二分查找的越界以及边界值初始化问题
    决策树知识梳理
    论文分类及写作基础
    Cypher 入门笔记
    python字符串拼接
    Spring、Hibernate 事务流程分析Session生命周期
  • 原文地址:https://www.cnblogs.com/cjyyb/p/7623972.html
Copyright © 2020-2023  润新知