bzoj 5056: OI游戏

来源:互联网 发布:linux 1.6 rpm bin 编辑:程序博客网 时间:2024/06/01 20:05

题意:

求最小路径树计数。

题解:

有一次感觉自己宛如智障。
首先看错题,想错题一小时……
然后发现看错了,结果重看又看错了,想错题半小时……
rp–,智商–。
其实直接spfa,求出每个点的最短路径上的边数目乘起来就可以了。
code:

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<queue>#include<algorithm>#define LL long longusing namespace std;const int mod=1000000007;queue<int> q;int n;struct node{    int x,y,c,next;}a[3010];int last[55],len=0;char ch[55];int dis[55];bool v[55];void ins(int x,int y,int c){    a[++len].x=x;a[len].y=y;a[len].c=c;    a[len].next=last[x];last[x]=len;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        scanf("%s",ch+1);        for(int j=1;j<=n;j++)            if(ch[j]!='0') ins(i,j,ch[j]-'0');    }    memset(v,false,sizeof(v));    memset(dis,63,sizeof(dis));    dis[1]=0;v[1]=true;q.push(1);    while(!q.empty())    {        int x=q.front();q.pop();v[x]=false;        for(int i=last[x];i;i=a[i].next)        {            int y=a[i].y;            if(dis[y]>dis[x]+a[i].c)            {                dis[y]=dis[x]+a[i].c;                if(!v[y]) v[y]=true,q.push(y);            }        }    }    LL ans=1;    for(int x=2;x<=n;x++)    {        LL tot=0;        for(int i=last[x];i;i=a[i].next)        {            int y=a[i].y;            if(dis[x]==dis[y]+a[i].c) tot++;        }        (ans*=tot)%=mod;    }    printf("%lld",ans);}
原创粉丝点击