poj 3249

     乍看似乎可以用拓扑排序,但由于数据量很大,一般会超时,至少我没去用。我的做法是加一个超级出发点0,将原图的各个分量组合起来,然后进行记忆化搜索。其中 dis[i],记录的是标号为i的结点到出度为0的点的最长距离,因此dis[0]即为所求。

     一开始时是用spfa()来做,一直超时,由于有负权,没敢用dijk+heap。因此,这时记忆化搜索就有用了。

      以下是代码:

 

  1. #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=101000;
    const int M=1100000;
    const __int64 inf=(__int64)1<<60;
    __int64 max(__int64 a,__int64 b) {return a>b?a:b;}
  2. struct node
    {
     int u,v;
     int next;
    }edge[2*M];
    int head[N],num;
    __int64 val[N];
    int ind[N],out[N];
    bool inst[N];
    int n,m;
  3. void init()
    {
     for(int i=0;i<=n+1;i++)
     {
      head[i]=-1;
      ind[i]=out[i]=0;
     }
     num=0;
    }
  4. void addege(int u,int v)
    {
     edge[num].u=u;
     edge[num].v=v;
     edge[num].next=head[u];
     head[u]=num++;
    }
  5. bool vis[N];
    __int64 dis[N];
    void dfs(int s)
    {
     int i,j;
     if(out[s]==0)
     {
      dis[s]=0;
      return ;
     }
     for(i=head[s];i!=-1;i=edge[i].next)
     {
      int v=edge[i].v;
      if(!vis[v])
      {
       vis[v]=1;
       dfs(v);
       dis[s]=max(dis[s],dis[v]+val[v]);
      }
      else
      {
       dis[s]=max(dis[s],dis[v]+val[v]);
      }
     }
    }
  6. int main()
    {
     while(scanf("%d%d",&n,&m)==2)
     {
      init();
      int i,j;
      int a,b;
      for(i=1;i<=n;i++)
       scanf("%I64d",&val[i]);
      while(m--)
      {
       scanf("%d%d",&a,&b);
       addege(a,b);
       out[a]++;
       ind[b]++;
      }
      for(i=1;i<=n;i++)
      {
       if(ind[i]==0)
       {
        addege(0,i);
        out[0]++;
       }
       dis[i]=-inf;
       vis[i]=0;
      }
      dis[0]=-inf;
      vis[0]=1;
      dfs(0);
      printf("%I64d/n",dis[0]);
     }
     return 0;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值