bzoj1179(缩点+乱搞)

来源:互联网 发布:手机游戏下载java 编辑:程序博客网 时间:2024/05/01 08:34

 

很显然这道就是需要先求出强连通分量,然后缩点。缩点之后就是有向无环图了。实际上这之后,各种方法就都可以了。

已知的dp:1.通过拓扑序用一个队列来进行dp,图是原先的图

                  2.缩点后建新图时,将图反向建。然后对于每一个酒吧,记忆话搜索,到市中心的最短路(我用的这种方法)

spfa:缩点后跑spfa,求出到每一个酒吧的最长路(我不敢确定这样的复杂度,就没写这个)

 

 

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<stack>using namespace std;inline int read(){    int ans,f=1;char ch;    while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;    ans=ch-'0';    while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';    return ans*f;}const int N=600005;const int inf=0x7777ffff;int n,m;int val1[N],val2[N];int dfn[N],low[N],size,pos[N],id;int f[N],S,P; struct aa{    int to[N*2],pre[N*2],head[N],tot;    void addedge(int x,int y)    {        to[++tot]=y;pre[tot]=head[x];head[x]=tot;    } }old,now; void init(){    n=read();m=read();    int x,y;    for (int i=1;i<=m;i++)    {        x=read();y=read();        old.addedge(x,y);    }    for (int i=1;i<=n;i++) val1[i]=read();}stack<int> s;bool in[N];void dfs(int u){    dfn[u]=low[u]=++id;    s.push(u);    in[u]=true;              for (int i=old.head[u];i;i=old.pre[i])    {        int v=old.to[i];        if (!dfn[v])        {            dfs(v);            low[u]=min(low[u],low[v]);        }        else if (in[v]) low[u]=min(low[u],dfn[v]);    }    if (dfn[u]==low[u])    {        size++;        int v;        do        {            v=s.top();            s.pop();            pos[v]=size;            val2[size]+=val1[v];            in[v]=false;         }while (v!=u);    }} void work_graph(){    for (int u=1;u<=n;u++)        for (int i=old.head[u];i;i=old.pre[i])        {            int v=old.to[i];            if (pos[u]!=pos[v])             now.addedge(pos[v],pos[u]);        }} void mx(int u){    if (f[u]!=-inf) return ;    if (u==pos[S])    {        f[u]=val2[u];        return ;    }    for (int i=now.head[u];i;i=now.pre[i])    {        int v=now.to[i];        mx(v);        f[u]=max(f[u],f[v]+val2[u]);    }} void work(){    S=read(),P=read();    for (int i=1;i<=size;i++) f[i]=-inf;    //注意用memset置的inf与实际的inf的大小是不一样的,    //这里的记忆化搜索需要判断是否来过(?==inf),就不能用memset,因为要保证一样     int ans=0;         for (int i=1;i<=P;i++)     {        int u=read();        mx(pos[u]);        ans=max(ans,f[pos[u]]);    }    printf("%d",ans);}int main(){    init();//读入     for (int i=1;i<=n;i++) if (!dfn[i]) dfs(i);//求出强连通分量 ,注意必须有这个循环!!!    work_graph();//缩点     work();//记忆花搜索,求出这些点的路径最大权值     return 0;} 

总结

1:这题wa了好几次,原因是缩点,只从1开始dfs了,实际上,可能会有许许多多的块,应该再各个部分都dfs一下!!!!强连通分量必须加那个循环!!!

2:这道题写了,邻接表的结构体,感觉对于缩点的题更为方便。

3:注意memset出的inf和实际的inf是不一样的,所以如果需要判断是否等于inf,在初始赋值的时候不能用memset。

 


 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 美的电饭煲不工作显示C3怎么办 美的电饭煲啪一声响不工作了怎么办 误给宝宝吃了坏的饭怎么办 鼠标没反应键盘指示灯不亮怎么办 新买变频冰箱风机声音大怎么办 三星手机玩王者荣耀一直闪退怎么办 刚申请的阿里大宝卡不想要了怎么办 国美刚买不到一个月电视坏了怎么办 交保险后保险公司不给开收据怎么办 收据白联作废红联丢失怎么办 收据作废客户联给客户了怎么办 宜家买的床和床垫搬家了怎么办 科龙空调开机后自己关机怎么办 以旧换新旧的没给商家 报案怎么办 想换新手机但是旧的没坏怎么办 从苏宁易购买的电视坏了怎么办 苏宁易购服务站买的电视坏了怎么办 用微信登陆京东账号退不出来怎么办 微信账号密码手机号都忘记了怎么办 我的手机号京东被别人绑定了怎么办 京东之前绑定的手机号不用了怎么办 京东退货钱未到银行卡账号里怎么办 京东身份证绑的手机号不用了怎么办 海尔冰箱要退货箱子扔了怎么办 海尔冰箱门变形关不严没吸力怎么办 长时间不用的手机忘记密码怎么办啊 微信忘记密码手机号又不用了怎么办 华为账号换了手机密码忘记了怎么办 用u盘制作音响喊话内容怎么办 新三板公司退市了小股东怎么办? 新三板公司退市股东股票怎么办 利群收购乐天玛特超市卡怎么办 买房过户夫妻一方是外省户口怎么办 欠了国美金融贷款没钱还会怎么办? 国企员工涨工资不在编的员工怎么办 装车牌照的螺丝孔小了怎么办 北京摇号之后中签和未中签怎么办 拉轿车的大车出车祸车怎么办 美图m6手机忘记锁屏密码怎么办 微信验证码登录收不到验证码怎么办 微信被限制登录收不到验证码怎么办