在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族。被族人恭称为“先知”的Alpaca L.Sotomon是这个家族的领袖,外人也称其为“所驼门王”。所驼门王毕生致力于维护家族的安定与和谐,他曾亲自率军粉碎河蟹帝国主义的野蛮侵略,为族人立下赫赫战功。所驼门王一生财宝无数,但因其生性节俭低调,他将财宝埋藏在自己设计的地下宫殿里,这也是今天Henry Curtis故事的起点。Henry是一个爱财如命的贪婪家伙,而又非常聪明,他费尽心机谋划了这次盗窃行动,破解重重机关后来到这座地下宫殿前。
整座宫殿呈矩阵状,由R×C间矩形宫室组成,其中有N间宫室里埋藏着宝藏,称作藏宝宫室。宫殿里外、相邻宫室间都由坚硬的实体墙阻隔,由一间宫室到达另一间只能通过所驼门王独创的移动方式——传送门。所驼门王为这N间藏宝宫室每间都架设了一扇传送门,没有宝藏的宫室不设传送门,所有的宫室传送门分为三种:
“横天门”:由该门可以传送到同行的任一宫室;
“纵寰门”:由该门可以传送到同列的任一宫室;
“自由门”:由该门可以传送到以该门所在宫室为中心周围8格中任一宫室(如果目标宫室存在的话)。
深谋远虑的Henry当然事先就搞到了所驼门王当年的宫殿招标册,书册上详细记录了每扇传送门所属宫室及类型。而且,虽然宫殿内外相隔,但他自行准备了一种便携式传送门,可将自己传送到殿内任意一间宫室开始寻宝,并在任意一间宫室结束后传送出宫。整座宫殿只许进出一次,且便携门无法进行宫室之间的传送。不过好在宫室内传送门的使用没有次数限制,每间宫室也可以多次出入。
现在Henry已经打开了便携门,即将选择一间宫室进入。为得到尽多宝藏,他希望安排一条路线,使走过的不同藏宝宫室尽可能多。请你告诉Henry这条路线最多行经不同藏宝宫室的数目。
这道题真是一道好(gou)题,我的做法似乎有点奇怪,不是像网上那样拓扑dp,而是跑最长路。首先强联通缩点,避免出现环的情况,之后我们把联通块连在一起,举个例子,x连y,则边权为y的节点数。再设两个点st与ed,别看题目说可以从任意宫室进入,任意宫室出去,但其实只需把st与入度为0的联通块相连(边权为联通块点数),出度为0的点与ed相连(边权为0)就可以了。为什么,因为这样可以保证走的最长,很好理解吧。最后再提醒一点,建边要优化,不然就算你其它都打对了,也只有40分,不要问我怎么知道的。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
int dx[8]={1,0,-1,0,1,1,-1,-1};
int dy[8]={0,1,0,-1,1,-1,1,-1};
struct node
{
int x,y,next;
}a[4110000];int len,last[210000];
struct bian
{
int x,y,c,bl;
}tr[210000];
struct edge
{
int x,y,c,next;
}b[3110000];int trlen,trlast[210000];
void trins(int x,int y,int c)
{
trlen++;
b[trlen].x=x;b[trlen].y=y;b[trlen].c=c;
b[trlen].next=trlast[x];trlast[x]=trlen;
}
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
}
int id,cnt,top;
int low[210000],dfn[210000];
int sta[210000],belong[210000],tot[210000],list[210000];
int chu[210000],ru[210000],ss[210000];
bool v[210000];
void dfs(int x)
{
dfn[x]=low[x]=++id;
sta[++top]=x;v[x]=true;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(dfn[y]==-1)
{
dfs(y);
low[x]=min(low[x],low[y]);
}
else
{
if(v[y]==true)low[x]=min(low[x],dfn[y]);
}
}
if(low[x]==dfn[x])
{
cnt++;int i;
do
{
i=sta[top--];
v[i]=false;
tot[cnt]++;
belong[i]=cnt;
}while(i!=x);
}
}
int cmp1(const void *xx,const void *yy)
{
bian n1=*(bian *)xx;
bian n2=*(bian *)yy;
if(n1.x==n2.x)
{
if(n1.y>n2.y)return 1;
if(n1.y<n2.y)return -1;
return 0;
}
if(n1.x>n2.x)return 1;
if(n1.x<n2.x)return -1;
return 0;
}
int cmp2(const void *xx,const void *yy)
{
bian n1=*(bian *)xx;
bian n2=*(bian *)yy;
if(n1.y>n2.y)return 1;
if(n1.y<n2.y)return -1;
return 0;
}
int n;
int erfen(int xx,int yy)
{
int l=1,r=n;
while(l<=r)
{
int mid=(l+r)/2;
if(tr[mid].x>xx)r=mid-1;
else if(tr[mid].x<xx)l=mid+1;
else if(tr[mid].y>yy)r=mid-1;
else if(tr[mid].y<yy)l=mid+1;
else return tr[mid].bl;
}
return -1;
}
int main()
{
len=0;memset(last,0,sizeof(last));
int R,C;
scanf("%d%d%d",&n,&R,&C);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&tr[i].x,&tr[i].y,&tr[i].c);
tr[i].bl=i;
}
qsort(tr+1,n,sizeof(bian),cmp2);
for(int i=1;i<=n;i++)
{
if(tr[i].c==2)
{
int j=i+1;
while(tr[i].y==tr[j].y)ins(tr[i].bl,tr[j].bl),j++;
j=i-1;
while(tr[i].y==tr[j].y)ins(tr[i].bl,tr[j].bl),j--;
}
}
qsort(tr+1,n,sizeof(bian),cmp1);
for(int i=1;i<=n;i++)
{
if(tr[i].c==1)
{
int j=i+1;
while(tr[i].x==tr[j].x)ins(tr[i].bl,tr[j].bl),j++;
j=i-1;
while(tr[i].x==tr[j].x)ins(tr[i].bl,tr[j].bl),j--;
}
}
for(int i=1;i<=n;i++)
{
if(tr[i].c==3)
{
for(int j=0;j<8;j++)
{
int xx=tr[i].x+dx[j],yy=tr[i].y+dy[j];
if(xx<1 || xx>R || yy<1 || yy>C)continue;
int ans=erfen(xx,yy);
if(ans!=-1)ins(tr[i].bl,ans);
}
}
}
id=cnt=top=0;
memset(dfn,-1,sizeof(dfn));
memset(low,0,sizeof(low));
memset(belong,0,sizeof(belong));
memset(v,false,sizeof(v));
memset(sta,0,sizeof(sta));
memset(tot,0,sizeof(tot));
for(int i=1;i<=n;i++)
{
if(dfn[i]==-1)dfs(i);
}
trlen=0;memset(trlast,0,sizeof(trlast));
for(int i=1;i<=len;i++)
{
if(belong[a[i].x]!=belong[a[i].y])
{
chu[belong[a[i].x]]++;
ru[belong[a[i].y]]++;
trins(belong[a[i].x],belong[a[i].y],tot[belong[a[i].y]]);
}
}
memset(ss,-1,sizeof(ss));
memset(v,false,sizeof(v));
int st=cnt+1,ed=cnt+2;
for(int i=1;i<=cnt;i++)
{
if(chu[i]==0)trins(i,ed,0);
if(ru[i]==0)trins(st,i,tot[i]);
}
int head=1,tail=2;ss[st]=0;
list[head]=st;v[st]=true;
while(head<=tail)
{
int x=list[head];
for(int k=trlast[x];k;k=b[k].next)
{
int y=b[k].y;
if(ss[y]<ss[x]+b[k].c)
{
ss[y]=ss[x]+b[k].c;
if(v[y]==false)
{
v[y]=true;
list[tail++]=y;
}
}
}
v[x]=false;
head++;
}
printf("%d\n",ss[ed]);
return 0;
}