zoukankan      html  css  js  c++  java
  • 并不对劲的noip2017d1t3

    因为A掉了d1t1,十分开心,把d1t3的代码调出来了。

    一般情况下,noip每一天总有一道dp题,然而d1前两道题都不是,再看看第三题的数据范围,就能大概猜出是dp了。

    这道题和最短路计数看上去很像。回想一下最短路计数的解法,大概是按照bfs序进行dp,dp[u]表示到节点u的条数。对于这道题而言,求的不是最短路条数而是长度不超过最短路+k的路径条数,那么就可以用dp[u][j]表示到节点u路径长度等于j的路径数。

    至于如何转移,用dis[x]表示x到1的最短路长度,则当dis[u]+w[k]+j-dis[x]<=k有dp[x][dis[u]+w[k]+j-dis[vv]]+=dp[u][j]。

    至于转移顺序,想到最短路计数是bfs序,而这道题有边权,那么就是dijkstra序(<-瞎编的词),其实就是dis[x]由小到大的顺序。

    至于0边,需要建一个新图,图中只有0边。用一个拓扑排序找出0环,若环上存在点x满足1到x的距离+x到n的距离<=1到n的距离+k,则这个环会被计数,输出-1。还有一点需要注意的是,当出现0边时,dp顺序不单单是dis[x]的顺序。当出现x--0-->y,显然是要先算dp[x]的。这是就需要用到之前算出的拓扑序,当两个点的dis相等时,先算拓扑序靠前的那个。

    下面是代码,我略作修改,使它有可能RE。

    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define stnd struct node
    #define nd node
    #define oops operator
    #define maxn 400010
    #define maxm 800010
    #define ll long long
    using namespace std;
    ll v[maxm],w[maxm],fir[maxn],nxt[maxm],cnt;//For roads.
    ll fv[maxm],fw[maxm],ffir[maxn],fnxt[maxm],fcnt;//For froads.
    ll tl,in[maxn],dep[maxn],ord[maxn],inq[maxn];//For topo sorting.
    ll n,m,inf,t,dp[maxn][60],kkk,p;;//For counting.
    ll dis[maxn],fdis[maxn];//For dijkstra.
    bool fl,vis[maxn][60];
    stnd
    {
        ll x,y;
        bool oops <(const nd &zz)const
        {
            return y>zz.y;
        }
    };
    inline ll read()
    {
        ll xx=0,ff=1;
        char ch=getchar();
        while(isdigit(ch)==0 && ch!='-')ch=getchar();
        if(ch=='-')ff=-1,ch=getchar();
        while(isdigit(ch))xx=xx*10+ch-'0',ch=getchar();
        return xx*ff;
    }
    void addedge(ll u1,ll v1,ll w1)
    {
        v[cnt]=v1,w[cnt]=w1,nxt[cnt]=fir[u1],fir[u1]=cnt++;
        fv[fcnt]=u1,fw[fcnt]=w1,fnxt[fcnt]=ffir[v1],ffir[v1]=fcnt++;
    }
    void dj()
    {
        memset(dis,0x7f,sizeof(dis));
        priority_queue<stnd>q;
        stnd tmp;
        tmp.x=1,tmp.y=0;
        dis[1]=0;
        q.push(tmp);
        while(!q.empty())
        {
            ll u=q.top().x,du=q.top().y;q.pop();
            if(dis[u]<du)continue;
            for(ll k=fir[u];k!=-1;k=nxt[k])
            {
                ll vv=v[k];
                if(dis[vv]>dis[u]+w[k])
                {
                    dis[vv]=dis[u]+w[k];
                    tmp.x=vv,tmp.y=dis[vv];
                    q.push(tmp);
                }
            }
        }
    }
    void fdj()
    {
        memset(fdis,0x7f,sizeof(fdis));
        priority_queue<stnd>q;
        stnd tmp;
        tmp.x=n,tmp.y=0;
        fdis[n]=0;
        q.push(tmp);
        while(!q.empty())
        {
            ll u=q.top().x,du=q.top().y;q.pop();
            if(fdis[u]<du)continue;
            for(ll k=ffir[u];k!=-1;k=fnxt[k])
            {
                ll vv=fv[k];
                if(fdis[vv]>fdis[u]+fw[k])
                {
                    fdis[vv]=fdis[u]+fw[k];
                    tmp.x=vv,tmp.y=fdis[vv];
                    q.push(tmp);
                }
            }
        }
    }
    void topoo(ll xx)
    {
        inq[xx]=1;
        ord[tl++]=xx;
        for(ll k=fir[xx];k!=-1;k=nxt[k])
        {
            if(w[k]!=0)continue;
            ll vv=v[k];
            in[vv]--;
            if(in[vv]==0)
                topoo(vv);
        }
        return;
    }
    void topo()
    {
        tl=1;
        memset(inq,0,sizeof(inq));
        memset(in,0,sizeof(in));
        for(ll i=0;i<m;i++)
            if(w[i]==0)in[v[i]]++;
        for(ll i=1;i<=n;i++)
            if(inq[i]==0 && in[i]==0)
                topoo(i);
        for(ll i=1;i<=n;i++)
        {
            if(in[i]!=0 && 
            dis[i]+fdis[i]<=dis[n]+kkk)
                fl=1;
        }
    }
    bool dfs(int u,int j)
    {
        if(vis[u][j])return 1;
        if(~dp[u][j])return 0;
        vis[u][j]=1;
        if(u==n)dp[u][j]=1;
        else dp[u][j]=0;
        for(int k=fir[u];k!=-1;k=nxt[k])
        {
            int vv=v[k],tt=dis[u]-dis[vv]+w[k]+j;
            if(tt<=kkk && 
            dis[u]+j+w[k]+fdis[vv]<=kkk+fdis[1])
            {
                if(dfs(vv,tt))return 1;
                dp[u][j]+=dp[vv][tt];
                dp[u][j]%=p; 
            }
        }
        vis[u][j]=0;
        return 0;
    }
    int main()
    {
        t=read();
        while(t--)
        {
            cnt=fcnt=fl=0;
            n=read(),m=read(),kkk=read(),p=read();
            memset(fir,-1,sizeof(fir));
            memset(ffir,-1,sizeof(ffir));
            memset(dp,-1,sizeof(dp));
            memset(vis,0,sizeof(vis));
            for(ll i=1;i<=m;i++)
            {
                ll x=read(),y=read(),z=read();
                addedge(x,y,z);
            }
            dj();
            fdj();
            topo();
            if(fl)cout<<-1;
            else
            {
                dfs(1,0);
                cout<<dp[1][0];
            }
            cout<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    获取<input type="checkbox" >控件的checked值
    网站IIS部署及调试
    winform窗体全屏实现
    ComBox控件的使用
    在vs2005项目中,将.sln文件和.suo文件放在一个独立的文件夹内
    .NET面试题整理
    《url重写——更友好的网站url设计》
    char、varchar、nvarchar三者间的区别
    操作符"??"的用法
    Maven 学习笔记(三)
  • 原文地址:https://www.cnblogs.com/xzyf/p/7998837.html
Copyright © 2011-2022 走看看