省选专练SDOI2010所驼门王的宝藏

来源:互联网 发布:2016网络小说知乎50 编辑:程序博客网 时间:2024/05/18 02:19

这是一个奇怪的题

首先,其思路和APIO2009-3掠夺计划相比难得多,数据变大了啊。

于是两两建边不可行,考虑用拉链判重。

从横天门或纵寰门引出的边可能特别多。在极端情况下,10^5个横天门在同一行里出现,这样时空复杂度都是无法承受的。考虑这一点进行优化:由于在同一行的横天门一定属于同一个强连通分量,所以在建边时,只需要对在同一行的横天门构建出一个环即可,不需要两两进行连边。而此行内的其他宫室,只需要从这个环中的任意一点向这个宫室连边即可。对于纵寰门也是一样。

然后缩了点想干嘛就干嘛top还是SPFA都可以

#include<iostream>#include<cstdio>#include<stack>#include<algorithm>#include<cmath>#include<cstring>#include<queue>#include<map>using namespace std;inline void read(int &x){    int f=1;    x=0;    char ch=getchar();    while(ch<'0'||ch>'9'){        if(ch=='-')            f=-1;        ch=getchar();    }    while(ch<='9'&&ch>='0'){        x=x*10+ch-'0';        ch=getchar();    }    x*=f;}int dx[]={0,1,0,-1,1,1,-1,-1};int dy[]={1,0,-1,0,-1,1,-1,1};int n,r,c;struct Front_star{    int u,v,w,nxt;}edge[5000000],e[5000000],ee[5000000];int cnt=0;int first[500000]={0};int head[500000]={0};struct Node{    int x,y,t;}pre[2000007]/*first array*/,nxt[2000007],a[2000007];void addedge(int u,int v,int w){    cnt++;    e[cnt].u=u;    e[cnt].v=v;    e[cnt].w=w;    e[cnt].nxt=first[u];    first[u]=cnt;}void adde(int u,int v,int w){    cnt++;    ee[cnt].u=u;    ee[cnt].v=v;    ee[cnt].w=w;    ee[cnt].nxt=head[u];    head[u]=cnt;}void add(){    for(int i=1;i<=n;i++){        if(a[i].t==1){            for(int j=pre[a[i].x].x;j;j=nxt[j].x){                if(i==j){                    continue;                }                addedge(i,j,1);            }        }        if(a[i].t==2){            for(int j=pre[a[i].y].y;j;j=nxt[j].y){                if(i==j){                    continue;                }                addedge(i,j,1);            }        }        if(a[i].t==3){            for(int k=0;k<8;k++){                int xx=a[i].x+dx[k];                for(int j=pre[xx].x;j;j=nxt[j].x){                    if(i==j)                        continue;                    if(abs(a[j].y-a[i].y)<=1)                    addedge(i,j,1);                }             }        }    }}int tot=0;//--------------int low[500000]={0};int dfn[500000]={0};int color[500000]={0};int siz[500000]={0};int inqueue[500000]={0};int scc=0;stack<int> S;void tarjan(int u){    tot++;    low[u]=dfn[u]=tot;    S.push(u);    inqueue[u]=1;    for(int i=first[u];i;i=e[i].nxt){        int v=e[i].v;        if(!dfn[v]){            tarjan(v);            low[u]=min(low[u],low[v]);        }        else{            if(inqueue[v]){                low[u]=min(low[u],dfn[v]);            }        }    }    if(low[u]==dfn[u]){        int x;        scc++;        do{            x=S.top();            S.pop();            color[x]=scc;            siz[scc]++;            inqueue[x]=0;        }while(x!=u);    }}int rd[500001]={0};int cd[500001]={0};int dis[500001]={0};void SPFA(){    queue<int>q;    for(int i=1;i<=scc;i++){        if(rd[i]==0){            q.push(i);            dis[i]=siz[i];        }    }    while(!q.empty()){        int x=q.front();        q.pop();        for(int i=head[x];i;i=ee[i].nxt){            int v=ee[i].v;            if(rd[v]==0)                continue;            rd[v]--;            if(dis[v]<dis[x]+siz[v]){                dis[v]=dis[x]+siz[v];            }            if(!rd[v]){                q.push(v);            }        }    }}int main(){    read(n);    read(r);    read(c);    for(int i=1;i<=n;i++){        int x,y,t;        read(x);        read(y);        read(t);        a[i].x=x;        a[i].y=y;        a[i].t=t;        nxt[i].x=pre[x].x;        pre[x].x=i;        nxt[i].y=pre[y].y;        pre[y].y=i;    }    add();    for(int i=1;i<=n;i++){        if(!dfn[i]){            tarjan(i);        }    }//cnt=0;//memset(first,0,sizeof(first));    for(int i=1;i<=n;i++){        for(int j=first[i];j;j=e[j].nxt){            int v=e[j].v;            int u=i;            if(color[u]!=color[v]){                adde(color[u],color[v],1);                rd[color[v]]++;                cd[color[u]]++;            }        }    }//for(int i=1;i<=scc;i++)//cout<<rd[i]<<" "<<siz[i]<<endl;    SPFA();    int ans=-1;//cout<<"4q382436939486724389279834"<<endl;    for(int i=1;i<=scc;i++){        ans=max(ans,dis[i]);//cout<<siz[i]<<" "<<cd[i]<<endl;    }    cout<<ans;}


原创粉丝点击