bzoj 1924: [Sdoi2010]所驼门王的宝藏 (tarjan缩点+spfa)

来源:互联网 发布:詹姆斯下赛季数据 编辑:程序博客网 时间:2024/06/05 15:40

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

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 854  Solved: 349
[Submit][Status][Discuss]

Description

Input

第一行给出三个正整数 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,所有的传送门位置互不相同。

Output

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

Sample Input

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

Sample Output

9

HINT

测试点编号 N R C 1 16 20 20 2 300 1,000 1,000 3 500 100,000 100,000 4 2,500 5,000 5,000 5 50,000 5,000 5,000 6 50,000 1,000,000 1,000,000 7 80,000 1,000,000 1,000,000 8 100,000 1,000,000 1,000,000 9 100,000 1,000,000 1,000,000 10 100,000 1,000,000 1,000,000

Source

[Submit][Status][Discuss]

题解:tarjan缩点+spfa

用tarjan缩点将图减小,然后用spfa跑最长路即可。

#include<iostream>  #include<cstdio>  #include<algorithm>  #include<cmath>  #include<cstring>  #include<map>  #include<vector> #include<queue> #define N 2000000  #define M 100003  #define pa pair<int,int>  using namespace std;  int m,n,x[M],y[M],opt[M],dis[M],can[M],val[M];  int point[N*2],next[N*2],v[N*2],ins[M],top,ans;  int head[N],nxt[N],c[N],dfsn[M],low[M],belong[M],st[N],cnt,sz,tot;  int posy[10]={-1,0,1,-1,1,-1,0,1},posx[10]={-1,-1,-1,0,0,1,1,1};  vector<int> line[M*10],row[M*10];  map<pa,int> mp;  void add(int x,int y)  {      tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y;      //cout<<x<<" "<<y<<endl;}  void build(int x,int y)  {      tot++; nxt[tot]=head[x]; head[x]=tot; c[tot]=y;  }  void tarjan(int x)  {      low[x]=dfsn[x]=++sz;      ins[x]=1; st[++top]=x;      for (int i=point[x];i;i=next[i])       if (!dfsn[v[i]])        {          tarjan(v[i]);          low[x]=min(low[x],low[v[i]]);        }       else if (ins[v[i]])  low[x]=min(low[x],dfsn[v[i]]);      if (low[x]==dfsn[x])       {          ++cnt;          int j;          do          {              j=st[top--];              ins[j]=0;              belong[j]=cnt;           }while(j!=x);       }  }  void spfa()  {      queue<int> p;      memset(dis,0,sizeof(dis));      memset(can,0,sizeof(can));      for (int i=1;i<=cnt;i++) if (!ins[i])  {  can[i]=1; dis[i]=val[i];  p.push(i);  }      while (!p.empty())       {          int now=p.front(); p.pop();          for (int i=head[now];i;i=nxt[i])           if (dis[c[i]]<dis[now]+val[c[i]])            {               dis[c[i]]=dis[now]+val[c[i]];               if (!can[c[i]])                {                  can[c[i]]=1;                   p.push(c[i]);                   }             }           can[now]=0;       }      for (int i=1;i<=cnt;i++)     ans=max(ans,dis[i]);}  int main()  {      int r,c;      scanf("%d%d%d",&n,&r,&c);      for (int i=1;i<=n;i++)       {          scanf("%d%d%d",&x[i],&y[i],&opt[i]);          line[x[i]].push_back(i);          row[y[i]].push_back(i);          mp[make_pair(x[i],y[i])]=i;       }      for (int i=1;i<=n;i++)       {          if (opt[i]==1){              int k=line[x[i]].size();              for (int j=0;j<k;j++)               if (line[x[i]][j]!=i)  add(i,line[x[i]][j]);           }          else          if (opt[i]==2)           {              int k=row[y[i]].size();              for (int j=0;j<k;j++)               if (row[y[i]][j]!=i) add(i,row[y[i]][j]);           }          else          {              for (int j=0;j<8;j++)               {                  int xx=posx[j]+x[i];                  int yy=posy[j]+y[i];                  if (xx>0&&yy>0&&xx<=r&&yy<=c)                   if (mp[make_pair(xx,yy)])                    add(i,mp[make_pair(xx,yy)]);               }          }       }      //cout<<tot<<endl;    for (int i=1;i<=n;i++)       if (!dfsn[i])  tarjan(i); //cout<<cnt<<endl;     for (int i=1;i<=n;i++)       val[belong[i]]++;      tot=0;      memset(ins,0,sizeof(ins));      for (int i=1;i<=n;i++)       for (int j=point[i];j;j=next[j])        if (belong[i]!=belong[v[j]])         build(belong[i],belong[v[j]]),ins[belong[v[j]]]++;//cout<<"!"<<endl;      spfa();    printf("%d\n",ans);  }  


0 0
原创粉丝点击