@ysner
2018-08-15T23:59:33.000000Z
字数 3165
阅读 2442
图论 tarjan 缩点
有一个的网格图,其中有个有门+宝藏的网格。这些门可以传送,且分为三类:
从任意点出发和终止,最多能经过多少有宝藏的网格。
首先可以考虑到的一个问题是,建边不能达到。
然而,如果门一都在同行,门二都在同列,就可以达到。
考虑把同行的门一、同列的门二用环连起来,
这样效果等价(强连通),建边复杂度降到。
然后再暴力连同行同列剩下的门(用环中的一点)和门三连的有宝藏网格即可。
这样弄完后,缩点+拓扑排序后跑最长路即可。(边权为联通块大小)
然而细节非常容易出锅:
1、如果中无值,访问和会。
(其实最好把它当一般数组用)
2、不需要判
3、如果有两张图,且把和搞混,就会莫名。
4、如果使用判重结构体,需要重载运算符并手写函数。
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#include<queue>#include<vector>#include<tr1/unordered_map>#define ll long long#define re register#define il inline#define max(a,b) ((a)>(b)?(a):(b))#define min(a,b) ((a)<(b)?(a):(b))#define fp(i,a,b) for(re int i=a;i<=b;i++)#define fq(i,a,b) for(re int i=a;i>=b;i--)using namespace std;const int N=1e5+100;struct Edge{int to,nxt;}e[N*50];struct node{int x,y,id;bool operator < (const node &o) const {return (x<o.x)||(x==o.x&&y<o.y);}}a[N];struct nnode{int x,y;bool operator == (const nnode &o) const {return x==o.x&&y==o.y;}}p[N*10];struct Hash{std::size_t operator () (const nnode &o) const{return o.x*N*10+o.y;};};int n,m,tot,h[N],cnt,fx[9]={0,1,-1,0,0,1,-1,1,-1},fy[9]={0,0,0,1,-1,1,-1,-1,1},low[N],dfn[N],st[N],tt,tim,sz[N],scc,bl[N],dis[N],T,in[N],ans,tmp[N];bool vis[N];vector<int>stan[N*10],stam[N*10];queue<int>Q;std::tr1::unordered_map<nnode,int,Hash>mp;il void add(re int u,re int v){e[++cnt]=(Edge){v,h[u]};h[u]=cnt;}il int gi(){re int x=0,t=1;re char ch=getchar();while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();if(ch=='-') t=-1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();return x*t;}il void tarjan(re int u){low[u]=dfn[u]=++tim;vis[u]=1;st[++tt]=u;re int v;for(re int i=h[u];i+1;i=e[i].nxt){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],dfn[v]);}if(low[u]==dfn[u]){++scc;do{v=st[tt];vis[v]=0;bl[v]=scc;sz[scc]++;tt--;}while(v!=u);}}int main(){memset(h,-1,sizeof(h));tot=gi();n=gi();m=gi();fp(i,1,tot) a[i].x=gi(),a[i].y=gi(),a[i].id=gi(),mp[(nnode){a[i].x,a[i].y}]=i;fp(i,1,tot){stan[a[i].x].push_back(i);stam[a[i].y].push_back(i);if(a[i].id==3)fp(j,1,8){re int xx=a[i].x+fx[j],yy=a[i].y+fy[j];if(xx<1&&xx>n&&yy<1&&yy>m) continue;if(mp[(nnode){xx,yy}]) add(i,mp[(nnode){xx,yy}]);}}fp(i,1,n){tt=0;for(re int j=0;j<stan[i].size();j++)if(a[stan[i][j]].id==1) tmp[++tt]=stan[i][j];fp(j,1,tt-1) add(tmp[j],tmp[j+1]);add(tmp[tt],tmp[1]);for(re int j=0;j<stan[i].size();j++)if(a[stan[i][j]].id!=1&&tt) add(tmp[1],stan[i][j]);}fp(i,1,m){tt=0;for(re int j=0;j<stam[i].size();j++)if(a[stam[i][j]].id==2) tmp[++tt]=stam[i][j];fp(j,1,tt-1) add(tmp[j],tmp[j+1]);add(tmp[tt],tmp[1]);for(re int j=0;j<stam[i].size();j++)if(a[stam[i][j]].id!=2&&tt) add(tmp[1],stam[i][j]);}tt=0;fp(i,1,tot) if(!dfn[i]) tarjan(i);fp(u,1,tot)for(re int i=h[u];i+1;i=e[i].nxt){re int v=e[i].to;if(bl[u]!=bl[v]) p[++T]=(nnode){bl[u],bl[v]};}memset(h,-1,sizeof(h));cnt=0;fp(i,1,T) add(p[i].x,p[i].y),in[p[i].y]++;fp(i,1,scc) if(!in[i]) Q.push(i);while(!Q.empty()){re int u=Q.front();Q.pop();dis[u]=max(dis[u],sz[u]);for(re int i=h[u];i+1;i=e[i].nxt){re int v=e[i].to;--in[v];if(in[v]==0) Q.push(v);dis[v]=max(dis[v],dis[u]+sz[v]);ans=max(ans,dis[v]);}}printf("%d\n",ans);return 0;}
