Sicily 1308. Dependencies among J

图论

今天训练的题目,题意:有一些工作要做必须等某些工作做完了才能开始,每个工作也要花费时间去做。输入先给出n,m,表示有n个工作,要求完成第m个工作的最短时间(工作从1到n标号),下面n行给出每个工作的信息,每行第一个数表示做这个工作要多少时间,后面可能有1个或多个或0个数字,表示这个工作要在这些工作做完后才能动工。另外注意一点,同一个时刻只能做一个人工作,不能同时进行多个工作

这题一开始看错,以为又是关键路径,敲了模板发现wa,才看到那句话,同一个时间只能做一个工作不能同时进行多个工作,因为这个条件,这道题可以说和关键路径就毫无关系了。后来想不出方法,在队友的提醒下想到了正解。

其实我们只要知道第m个工作前面有多少个工作,每个工作的时间只能被计算一次

好像1-->2-->3-->4 ,   2--->4 ,  1-->5--->4

在4只能的点有1,2,3,5,这些点都影响了4,但是俺路径来算,要按点来算,每个点的时间只能算一次,所以完成4的最早时间就是

T[4]=val[1]+val[2]+val[3]+val[5]+val[4];  (做它本身也需要时间)

但是怎么知道m前面有哪些点呢,队友提示,图是有向图而且保证了无环,那么只要把所有有向边取反,从m点出发,遍历一次图即可,因为从m出发能去到的点,在取反前应该是这些点能去到m,而且遍历的话就能保证每个点只被访问一次,时间也就只计算了一次

 

用了vector建图,如果手动模拟邻接表的话时间会快些

#include <cstdio>

#include <cstring>

#include <vector>

using namespace std;

#define N 10010



vector<int>a[N];

int val[N];

int n,m;

bool vis[N];

int res;



void dfs(int u)

{

    vis[u]=true;

    res += val[u];

    int size=a[u].size();

    for(int i=0; i<size; i++)

        if(!vis[ a[u][i] ])

            dfs(a[u][i]);

    return ;

}



void solve()

{

    res=0;

    memset(vis,0,sizeof(vis));

    dfs(m);

    printf("%d\n",res);

}



int main()

{

    //freopen("input.txt","r",stdin);

    while(scanf("%d",&n)!=EOF && n)

    {

        scanf("%d",&m);

        for(int i=1; i<=n; i++)

            a[i].clear();

        for(int i=1; i<=n; i++)

        {

            char ch;

            int u,v;

            scanf("%d",&val[i]);

            ch=getchar();

            if(ch=='\n') continue;

            while(1)

            {

                scanf("%d",&u);

                a[i].push_back(u);

                ch=getchar();

                if(ch=='\n')

                    break;

            }

        }

        solve();

    }

    return 0;

}

 

你可能感兴趣的:(IE)