NOIP2017D1T3

考场上未曾光顾的一道题...

结果回来20min想出方程1hA掉了

我是真的蒻,Orz机房里其他的各位dalao

图上dp

两遍spfa(我写的dijkstra)判断一个点对答案的贡献

然后随便dp一下

零环在dp的时候单独处理一下,如果访问过一个点又访问回来了且目前超过的长度没变就是零环

然后就轻松加愉快咯

110行

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int inf=2147483233;
const int maxn=400010;
#define pa pair<int,int>
int n,m,k,T,P;
int first[maxn],next[maxn],to[maxn],val[maxn],cnt;
int First[maxn],Next[maxn],To[maxn],Val[maxn],Cnt;
int u,v,w;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
    return x*f;
}
inline void add(int u,int v,int w){to[++cnt]=v;next[cnt]=first[u];first[u]=cnt;val[cnt]=w;}
inline void Add(int u,int v,int w){To[++Cnt]=v;Next[Cnt]=First[u];First[u]=Cnt;Val[Cnt]=w;}
int dis[maxn],Dis[maxn];
int dp[maxn][60];
int used[maxn][60];
int ans;
void dj()
{
    priority_queue<pa,vector<pa>,greater<pa> > heap;
    dis[1]=0;
    heap.push(make_pair(0,1));
    while(!heap.empty())
    {
        int now=heap.top().second,no=heap.top().first;heap.pop();
        if(dis[now]<no)continue;
        for(int i=first[now];i;i=next[i])
            if(dis[to[i]]==-1 || dis[to[i]]>dis[now]+val[i])
            {
                dis[to[i]]=dis[now]+val[i];
                heap.push(make_pair(dis[to[i]],to[i]));
            }
    }
}
void DJ()
{
    priority_queue<pa,vector<pa>,greater<pa> > heap;
    Dis[n]=0;
    heap.push(make_pair(0,n));
    while(!heap.empty())
    {
        int now=heap.top().second,no=heap.top().first;heap.pop();
        if(Dis[now]<no)continue;
        for(int i=First[now];i;i=Next[i])
            if(Dis[To[i]]==-1 || Dis[To[i]]>Dis[now]+Val[i])
            {
                Dis[To[i]]=Dis[now]+Val[i];
                heap.push(make_pair(Dis[To[i]],To[i]));
            }
    }
}
int solve(int u,int sum)
{
    if(used[u][sum])return 1;
    if(~dp[u][sum])return 0;
    used[u][sum]=1;
    if(u==n)dp[u][sum]=1;
    else dp[u][sum]=0;
    int cur;
    for(int i=first[u];i;i=next[i])
    {
        cur=dis[u]-dis[to[i]]+val[i]+sum;
        if(cur<=k && dis[u]+sum+val[i]+Dis[to[i]]-ans<=k)
        {
            if(solve(to[i],cur))return 1;
            dp[u][sum]+=dp[to[i]][cur];
            if(dp[u][sum]>=P)dp[u][sum]-=P;
        }
    }
    used[u][sum]=0;
    return 0;
}
int main()
{
    T=read();
    while(T--)
    {
        n=read(),m=read(),k=read(),P=read();cnt=0,Cnt=0,ans=0;
        memset(first,0,sizeof(first));memset(to,0,sizeof(to));
        memset(next,0,sizeof(next));memset(val,0,sizeof(val));
        memset(First,0,sizeof(First));memset(To,0,sizeof(To));
        memset(Next,0,sizeof(Next));memset(Val,0,sizeof(Val));
        memset(dp,0xff,sizeof(dp));memset(used,0,sizeof(used));
        memset(Dis,0xff,sizeof(Dis));memset(dis,0xff,sizeof(dis));
        for(int i=1;i<=m;i++)
        {
            u=read(),v=read(),w=read();
            add(u,v,w);
            Add(v,u,w);
        }
        dj();
        DJ();
        ans=Dis[1];
        if(solve(1,0))puts("-1");
        else printf("%d\n",dp[1][0]);
    }
    return 0;
}
View Code

 

posted @ 2017-12-06 17:45  探险家Mr.H  阅读(299)  评论(0编辑  收藏  举报