【codevs2131】【BZOJ1924】所驼门王的宝藏,tarjan+拓扑DP

原创 2016年06月01日 17:41:51

Time:2016.06.01
Author:xiaoyimi
转载注明出处谢谢


传送门1
传送门2
思路:
比较简单
使用规则建出一个包含N个点的无向图来,然后tarjan,得到重构后的有向无环图,然后拓扑DP就可以了
f[u]代表以i为起点所能走到的最多的点数
f[u]=max(f[v])(u,v)E
由DP方程我们可以开出来要求出点i的f值,必须要求它所有能到达的点的f值,所以我们可以反向建图拓扑排序,这样就能求出全部的f值了
注意:
1.建原图时处理起来很烦人,我用vector存储同一行、列的点,map存储周围一圈的点,所以常数大得吓人……
2.存边的数组一定要开大点……
代码:

#include<bits/stdc++.h>
#include<map>
#define M 100004
#define LL long long
using namespace std;
int in()
{
    int t=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) t=(t<<3)+(t<<1)+ch-48,ch=getchar();
    return t;
}
int k=in(),n=in(),m=in(),tot,cnt;
int IN[M],OUT[M],f[M],belong[M],siz[M],low[M],dfn[M],X[M],Y[M],T[M],first[M];
int dx[8]={0,0,-1,-1,-1,1,1,1},dy[8]={-1,1,-1,0,1,-1,0,1};
vector<int>a[M*10],b[M*10];
bool vis[M];
stack<int>S;
queue<int>Q; 
map<LL,int>mp;
struct edge{int v,next;}e[M*40];
void add(int x,int y){e[++tot]=(edge){y,first[x]};first[x]=tot;}
void dfs(int x)
{
    low[x]=dfn[x]=++cnt;
    S.push(x);
    vis[x]=1;
    for (int i=first[x];i;i=e[i].next)
        if (!dfn[e[i].v])
            dfs(e[i].v),
            low[x]=min(low[e[i].v],low[x]);
        else if (vis[e[i].v])
            low[x]=min(dfn[e[i].v],low[x]);
    if(low[x]==dfn[x])
        for (int y=-1;y!=x;y=S.top(),S.pop())
            siz[x]++,
            vis[S.top()]=0,
            belong[S.top()]=x;
}
main()
{
    for (int i=1;i<=k;i++)
        X[i]=in(),Y[i]=in(),T[i]=in(),
        mp[(LL)(X[i]-1)*m+Y[i]]=i,
        a[X[i]].push_back(i),
        b[Y[i]].push_back(i);
    for (int i=1;i<=k;i++)
    {
        if(T[i]==1)
            for (int j=0;j<a[X[i]].size();j++)
                if (i!=a[X[i]][j]) add(i,a[X[i]][j]);
                else;
        else if (T[i]==2)
            for (int j=0;j<b[Y[i]].size();j++)
                if (i!=b[Y[i]][j]) add(i,b[Y[i]][j]);
                else;
        else
            for (int j=0;j<8;j++)
            {
                LL t=(LL)(X[i]+dx[j]-1)*m+Y[i]+dy[j];
                int x=mp[t];
                if(x) add(i,x);
            }
    }
    for (int i=1;i<=k;i++)
        if(!dfn[i]) dfs(i);
    tot=0;
    memset(first,0,sizeof(first));
    for (int i=1;i<=k;i++)
    {
        if(T[i]==1)
            for (int j=0;j<a[X[i]].size();j++)
                if (belong[i]!=belong[a[X[i]][j]])
                    IN[belong[i]]++,
                    OUT[a[X[i]][j]]++,
                    add(belong[a[X[i]][j]],belong[i]);
                else; 
        else if (T[i]==2)
            for (int j=0;j<b[Y[i]].size();j++)
                if (belong[i]!=belong[b[Y[i]][j]])
                    IN[belong[i]]++,
                    OUT[b[Y[i]][j]]++, 
                    add(belong[b[Y[i]][j]],belong[i]);
                else;
        else
            for (int j=0;j<8;j++)
            {
                LL t=(LL)(X[i]+dx[j]-1)*m+Y[i]+dy[j];
                int x=mp[t];
                if(x&&belong[i]!=belong[x])
                    IN[belong[i]]++,
                    OUT[belong[x]]++,
                    add(belong[x],belong[i]);
            }
    }
    for (int i=1;i<=k;i++)
        if (!IN[i]&&siz[i])
            Q.push(i),
            f[i]=siz[i];
    for (;!Q.empty();Q.pop())
    {
        int x=Q.front();vis[x]=0;
        for (int i=first[x];i;i=e[i].next)
        {
            if (f[e[i].v]<f[x]+siz[e[i].v]) f[e[i].v]=f[x]+siz[e[i].v];
            IN[e[i].v]--;
            if (!IN[e[i].v]) Q.push(e[i].v);
        }
    }
    for (int i=1;i<=k;i++)
        f[0]=max(f[0],f[i]);
    printf("%d",f[0]);
}
版权声明:不转不是中国人!(滑稽)

BZOJ 1924 [Sdoi2010]所驼门王的宝藏 tarjan缩点+拓扑DP

BZOJ 1924 [Sdoi2010]所驼门王的宝藏 tarjan缩点+拓扑DP
  • wzq_QwQ
  • wzq_QwQ
  • 2015年10月13日 17:01
  • 3094

1924: [Sdoi2010]所驼门王的宝藏 tarjan缩点+dp最长路

读完题感觉很是凌乱,看到数据范围又一阵冷汗,仔细看一下题,其实就是给你了点之间的关系,建边后先缩一下点,重建图后dp一下就好了。 好吧用了一下stl。。 #include #include #inc...

bzoj1924 [Sdoi2010]所驼门王的宝藏

目标在我们遥不可及的地方,我们难道就只能翘首仰望么?

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

传送门 我们首先可以用O(NlogN)的时间建出来所有的边。 然后我们大力tarjan求联通块 之后大力拓扑排序一发就可以了。#include #include #include #inclu...

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

Description Input 第一行给出三个正整数 N, R, C。 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在...

[SDOI2010]BZOJ 1924所驼门王的宝藏-强连通分量-缩点-拓扑排序-dp

题目链接:右转进入题目 题目大意:自行参考题目 题解:tarjan缩点后拓排一下dp乱搞即可。 代码://BZOJ 1924 //SDOI 2010 #include #include #includ...
  • Mys_C_K
  • Mys_C_K
  • 2017年04月25日 16:59
  • 152

bzoj1924 所驼门王的宝藏 有向图最长链

思路还是简单的,代码就。。。。反正bzoj上比我快的都比我长(3k+)     显然,如果把每个点向它能到达的点连一条有向边,那么答案就是这个图的最长链(废话)。然后就是一个景点的强连通分量缩点+dp...

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

1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec  Memory Limit: 128 MB Submit: 875  Solved: 359 [Submit]...

[BZOJ 1093][ZJOI2007]最大半连通子图(Tarjan+拓扑排序+Dp)

Description  一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:u,v∈V,满足u→v或v→u,即对于图中任意 两点u,v,存在一条u到v的有向路径或者从v...
  • zars19
  • zars19
  • 2017年03月26日 02:01
  • 128

BZOJ 1512 [POI2006]Pro-Professor Szu Tarjan缩点+拓扑DP

BZOJ 1512 [POI2006]Pro-Professor Szu Tarjan缩点+拓扑DP
  • wzq_QwQ
  • wzq_QwQ
  • 2015年10月20日 07:04
  • 1418
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【codevs2131】【BZOJ1924】所驼门王的宝藏,tarjan+拓扑DP
举报原因:
原因补充:

(最多只允许输入30个字)