Codeforces 214C Game【思维+拓扑排序】

C. Game
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Furik and Rubik love playing computer games. Furik has recently found a new game that greatly interested Rubik. The game consists of nparts and to complete each part a player may probably need to complete some other ones. We know that the game can be fully completed, that is, its parts do not form cyclic dependencies.

Rubik has 3 computers, on which he can play this game. All computers are located in different houses. Besides, it has turned out that each part of the game can be completed only on one of these computers. Let's number the computers with integers from 1 to 3. Rubik can perform the following actions:

  • Complete some part of the game on some computer. Rubik spends exactly 1 hour on completing any part on any computer.
  • Move from the 1-st computer to the 2-nd one. Rubik spends exactly 1 hour on that.
  • Move from the 1-st computer to the 3-rd one. Rubik spends exactly 2 hours on that.
  • Move from the 2-nd computer to the 1-st one. Rubik spends exactly 2 hours on that.
  • Move from the 2-nd computer to the 3-rd one. Rubik spends exactly 1 hour on that.
  • Move from the 3-rd computer to the 1-st one. Rubik spends exactly 1 hour on that.
  • Move from the 3-rd computer to the 2-nd one. Rubik spends exactly 2 hours on that.

Help Rubik to find the minimum number of hours he will need to complete all parts of the game. Initially Rubik can be located at the computer he considers necessary.

Input

The first line contains integer n (1 ≤ n ≤ 200) — the number of game parts. The next line contains n integers, the i-th integer — ci(1 ≤ ci ≤ 3) represents the number of the computer, on which you can complete the game part number i.

Next n lines contain descriptions of game parts. The i-th line first contains integer ki (0 ≤ ki ≤ n - 1), then ki distinct integers ai, j(1 ≤ ai, j ≤ nai, j ≠ i) — the numbers of parts to complete before part i.

Numbers on all lines are separated by single spaces. You can assume that the parts of the game are numbered from 1 to n in some way. It is guaranteed that there are no cyclic dependencies between the parts of the game.

Output

On a single line print the answer to the problem.

Examples
input
1
1
0
output
1
input
5
2 2 1 1 3
1 5
2 5 1
2 5 4
1 5
0
output
7
Note

Note to the second sample: before the beginning of the game the best strategy is to stand by the third computer. First we complete part 5. Then we go to the 1-st computer and complete parts 3 and 4. Then we go to the 2-nd computer and complete parts 1 and 2. In total we get 1+1+2+1+2, which equals 7 hours.


题目大意:


现在有三个工作站,有三种工作,每种工作需要完成前置任务才能进行当前工作,三个工作站之间转换需要花费时间,问将所有任务都完成需要花费的最少时间。一开始可以在任意一个工作站开始工作。


思路:

仔细观察三个工作站之间转换需要花费的时间不难发现,我们从1如果想要去3的话,不妨先到2一次,再到3,距离都是2.

同理,如果想从2到1的话,不妨先到3一次,再到1,距离也是2.

那么其实我们就可以枚举一个起点,然后每一次将当前站(now)能够做的工作全部做完,然后转到下一个工作站继续工作(now+1)去进行能够进行的工作即可。

那么整个工作的过程就是不断的1->2->3->1->2->3去循环往复的做就行了。直到所有任务都完成。

做任务的过程暴力拓扑一下就行。


Ac代码:

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
vector<int>mp[15000];
int d[5][5];
int a[2500];
int degree[2500];
int n;
int Slove(int ss)
{
    queue<int>s;
    int ans=n;
    int cont=0;
    int now=ss;
    while(1)
    {
        while(1)
        {
            int flag=0;
            for(int i=1;i<=n;i++)
            {
                if(degree[i]==0&&a[i]==now)
                {
                    flag=1;
                    degree[i]=-1;
                    cont++;
                    for(int j=0;j<mp[i].size();j++)
                    {
                        int v=mp[i][j];
                        degree[v]--;
                    }
                }
            }
            if(flag==0)break;
        }
        if(cont==n)break;
        now++;
        ans++;
        if(now==4)now=1;
    }
    return ans;
}
int temp[15000];
int main()
{
    d[1][1]=0;d[1][2]=1;d[1][3]=2;
    d[2][1]=2;d[2][2]=1;d[2][3]=1;
    d[3][1]=1;d[3][2]=1;d[3][3]=0;
    while(~scanf("%d",&n))
    {
        memset(degree,0,sizeof(degree));
        for(int i=1;i<=n;i++)mp[i].clear();
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
        {
            int ki;scanf("%d",&ki);
            for(int j=1;j<=ki;j++)
            {
                int x;scanf("%d",&x);
                mp[x].push_back(i);
                degree[i]++;
            }
        }
        for(int i=1;i<=n;i++)temp[i]=degree[i];
        int ans=0x3f3f3f3f;
        for(int i=1;i<=n;i++)degree[i]=temp[i];
        ans=min(ans,Slove(1));
        for(int i=1;i<=n;i++)degree[i]=temp[i];
        ans=min(ans,Slove(2));
        for(int i=1;i<=n;i++)degree[i]=temp[i];
        ans=min(ans,Slove(3));
        printf("%d\n",ans);
    }
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值