Codeforces 284E Coin Troubles【思维+拓扑排序+完全背包】好题!

351 篇文章 2 订阅
35 篇文章 0 订阅

E. Coin Troubles
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

In the Isle of Guernsey there are n different types of coins. For each i (1 ≤ i ≤ n), coin of type i is worth ai cents. It is possible that ai = ajfor some i and j (i ≠ j).

Bessie has some set of these coins totaling t cents. She tells Jessie q pairs of integers. For each i (1 ≤ i ≤ q), the pair bi, ci tells Jessie that Bessie has a strictly greater number of coins of type bi than coins of type ci. It is known that all bi are distinct and all ci are distinct.

Help Jessie find the number of possible combinations of coins Bessie could have. Two combinations are considered different if there is some i (1 ≤ i ≤ n), such that the number of coins Bessie has of type i is different in the two combinations. Since the answer can be very large, output it modulo 1000000007 (109 + 7).

If there are no possible combinations of coins totaling t cents that satisfy Bessie's conditions, output 0.

Input

The first line contains three space-separated integers, n, q and t (1 ≤ n ≤ 300; 0 ≤ q ≤ n; 1 ≤ t ≤ 105). The second line contains n space separated integers, a1, a2, ..., an (1 ≤ ai ≤ 105). The next q lines each contain two distinct space-separated integers, bi and ci(1 ≤ bi, ci ≤ nbi ≠ ci).

It's guaranteed that all bi are distinct and all ci are distinct.

Output

A single integer, the number of valid coin combinations that Bessie could have, modulo 1000000007 (109 + 7).

Examples
input
4 2 17
3 1 2 5
4 2
3 4
output
3
input
3 2 6
3 1 1
1 2
2 3
output
0
input
3 2 10
1 2 3
1 2
2 1
output
0
Note

For the first sample, the following 3 combinations give a total of 17 cents and satisfy the given conditions: {0 of type 1, 1 of type 2, 3 of type 3, 2 of type 4}, {0, 0, 6, 1}, {2, 0, 3, 1}.

No other combinations exist. Note that even though 4 occurs in both bi and ci,  the problem conditions are still satisfied because all bi are distinct and all ci are distinct.


题目大意:


有n种硬币,现在我们需要凑出t价值的硬币,我们每种硬币都可以任取数量,不过要满足q个约束。

对于每个约束,(a,b)表示需要a种类的硬币使用的个数多余b种类的硬币。


思路:


①对于依赖(a,b),如果我们拿了一个b硬币,那么肯定同时也要拿至少一个a硬币,那么我们可以预处理一下,令一开始的时候,我们是满足所有约束条件的。

那么过程其实就相当于建个反图,然后将t-=a【i】*d,d表示从度为0的点拓扑到当前点链的长度。这样的话我们就能够使得初始的时候,我们是满足所有约束条件的。


②那么接下来,我们考虑拿一个b硬币的时候,同时也要再拿一个a硬币才能继续保证满足约束条件。所以我们再拓扑排序一下过程使得a【v】+=a【u】,然后构建出新的物品集合,然后再跑完全背包即可。


具体细节参考代码;


Ac代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define mod 1000000007
#define ll __int64
ll wupin[350];
vector<ll>mp[350];
ll a[350];
ll b[350];
ll dp[150000];
ll degree[150000];
ll vis[150000];
ll n,q,t;
void Top()
{
    queue<ll>s;
    memset(dp,0,sizeof(dp));
    for(ll i=1;i<=n;i++)
    {
        if(degree[i]==0)
        {
            s.push(i);
        }
    }
    ll cnt=0;
    int cont=0;
    while(!s.empty())
    {
        ll u=s.front();s.pop();
        cont++;
        if(vis[u]>0)t-=a[u]-b[u];
        if(a[u]<=t)wupin[cnt++]=a[u];
        for(ll i=0;i<mp[u].size();i++)
        {
            ll v=mp[u][i];
            a[v]+=a[u];
            degree[v]--;
            if(degree[v]==0)s.push(v);
        }
    }
    dp[0]=1;
    for(ll i=0;i<cnt;i++)
    {
        for(ll j=wupin[i];j<=t;j++)
        {
            dp[j]+=dp[j-wupin[i]];
            dp[j]%=mod;
        }
    }
    if(t>=0&&cont==n)
    printf("%I64d\n",dp[t]);
    else printf("0\n");
}
int main()
{
    while(~scanf("%I64d%I64d%I64d",&n,&q,&t))
    {
        memset(vis,0,sizeof(vis));
        memset(degree,0,sizeof(degree));
        for(ll i=1;i<=n;i++)mp[i].clear();
        for(ll i=1;i<=n;i++)scanf("%I64d",&a[i]),b[i]=a[i];
        for(ll i=0;i<q;i++)
        {
            ll x,y;scanf("%I64d%I64d",&x,&y);
            vis[x]++,vis[y]++;
            mp[x].push_back(y);
            degree[y]++;
        }
        Top();
    }
}













  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值