andre_joy

导航

zoj 3644

地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4834

题意:一个有向图,从1出发,到n,初始分数是位置1的分数,每走一步,分数变为之前分数跟当前位置分数的最小公倍数,题目规定每走一步分数必须变化。求多少种方案走到n达到分数k。

mark:用bfs做的。正在处于学习STL阶段,写了很长时间。

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#define LL long long

using namespace std;

const int MOD = 1000000007;
const int N = 2010;
int n,m,k,cnt;
int w[N],vst[N];
map <int, int> dp[N];
vector<int> vv[N];

int gcd(int m, int n)
{
    if(n == 0) return m;
    return gcd(n, m%n);
}

int bfs()
{
    int i,j;
    int ret = 0;
    queue<int> qq;
    qq.push(1);
    vst[1] = 1;
    dp[1][w[1]] = 1;
    map<int, int>::iterator it;
    while(!qq.empty())
    {
        int q = qq.front();
        qq.pop();
        vst[q] = 0;
        if(q == n) ret = (ret+dp[q][k])%MOD;
        int ii = vv[q].size();
        for(i = 0; i < ii; i++)
        {
            int s = vv[q][i];
            for(it = dp[q].begin(); it != dp[q].end(); it++)
            {
                int tem = it->first;
                int ans = tem/gcd(tem, w[s])*w[s];
                if(ans == tem || k%ans) continue;
                dp[s][ans] = (dp[s][ans]+it->second)%MOD;
                if(!vst[s])
                {
                    vst[s] = 1;
                    qq.push(s);
                }
            }
        }
        dp[q].clear();
    }
    return ret;
}

int main()
{
    int i,j;
    while(~scanf("%d%d%d", &n, &m, &k))
    {
        for(i = 0; i < n; i++) vv[i].clear();
        int aa,bb;
        for(i = 0; i < m; i++)
        {
            scanf("%d%d", &aa, &bb);
            vv[aa].push_back(bb);
        }
        for(i = 1; i <= n; i++)
            scanf("%d", w+i);
        memset(vst, 0, sizeof(vst));
        printf("%d\n", bfs());
    }
    return 0;
}

posted on 2012-10-01 11:59  andre_joy  阅读(272)  评论(0编辑  收藏  举报