洛谷 P3627 [APIO2009]抢掠计划 题解

Analysis

建图+强连通分量+SPFA求最长路

但要保证最后到达的点中包含酒馆

虽然思路并不难想,但要求的代码能力很高。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #define maxn 500010
  7 using namespace std;
  8 inline int read() 
  9 {
 10     int x=0;
 11     bool f=1;
 12     char c=getchar();
 13     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
 14     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
 15     if(f) return x;
 16     return 0-x;
 17 }
 18 inline void write(int x)
 19 {
 20     if(x<0){putchar('-');x=-x;}
 21     if(x>9)write(x/10);
 22     putchar(x%10+'0');
 23 }
 24 struct node
 25 {
 26     int from,to,val,nex;
 27 }edge[2*maxn];
 28 int n,m,s,p,cnt,ans,top,inl,num;
 29 int x[maxn],y[maxn],head[maxn],dfn[maxn],low[maxn],st[maxn],inn[maxn],sum[maxn],si[maxn],money[maxn],dis[maxn];
 30 bool book[maxn],book1[maxn],bar[maxn];
 31 inline void clear()
 32 {
 33     cnt=0;
 34     memset(edge,0,sizeof(edge));
 35     memset(head,0,sizeof(head));
 36 }
 37 inline void add(int x,int y)
 38 {
 39     cnt++;
 40     edge[cnt].to=y;
 41     edge[cnt].nex=head[x];
 42     head[x]=cnt;
 43 }
 44 inline void build(int x,int y,int z)
 45 {
 46     cnt++;
 47     edge[cnt].from=x;
 48     edge[cnt].to=y;
 49     edge[cnt].val=z;
 50     edge[cnt].nex=head[x];
 51     head[x]=cnt;
 52 }
 53 inline void Tarjan(int u)
 54 {
 55     dfn[u]=low[u]=++num;
 56     st[++top]=u;
 57     for(int i=head[u];i;i=edge[i].nex)
 58     {
 59         int v=edge[i].to;
 60         if(!dfn[v])
 61         {
 62             Tarjan(v);
 63             low[u]=min(low[u],low[v]);
 64         }
 65         else if(!inn[v])
 66             low[u]=min(low[u],dfn[v]);
 67     }
 68     if(low[u]==dfn[u])
 69     {
 70         inn[u]=++inl;
 71         while(st[top]!=u)
 72         {
 73             if(bar[st[top]])book1[inl]=1;
 74             sum[inl]+=money[st[top]];
 75             inn[st[top]]=inl;
 76              --top;
 77         }
 78         if(bar[st[top]])book1[inl]=1;
 79         sum[inl]+=money[st[top]];
 80         --top;
 81     }
 82 }
 83 inline void spfa()
 84 {
 85     memset(book,0,sizeof(book));
 86     for(int i=1;i<=n;i++) dis[i]=0;
 87     queue<int> q;
 88     q.push(inn[s]);
 89     book[inn[s]]=1;
 90     dis[inn[s]]=sum[inn[s]];
 91     while(!q.empty())
 92     {
 93         for(int i=head[q.front()];i;i=edge[i].nex)
 94         {
 95             if(dis[edge[i].to]<dis[edge[i].from]+edge[i].val)
 96             {
 97                 dis[edge[i].to]=dis[edge[i].from]+edge[i].val;
 98                 if(book[edge[i].to]==0)
 99                 {
100                     q.push(edge[i].to);
101                     book[edge[i].to]=1;
102                 }
103             }
104         }
105         book[q.front()]=0;
106         q.pop();
107     }
108 }
109 int main()
110 {
111     n=read();m=read();
112     for(int i=1;i<=m;i++)
113     {
114         x[i]=read();y[i]=read();
115         add(x[i],y[i]);
116     }
117     for(int i=1;i<=n;i++)money[i]=read();
118     s=read();p=read();
119     
120     for(int i=1;i<=p;i++)
121     {
122         int x;
123         x=read();
124         bar[x]=1;
125     }
126     for(int i=1;i<=n;i++)
127         if(!dfn[i])
128             Tarjan(i);
129     
130     clear();
131     for(int i=1;i<=m;i++)
132         if(inn[x[i]]!=inn[y[i]])
133             build(inn[x[i]],inn[y[i]],sum[inn[y[i]]]);
134     spfa();
135     for(int i=1;i<=inl;i++)
136         if(book1[i]==1)
137             ans=max(ans,dis[i]);
138     write(ans);
139     return 0;
140 }
请各位大佬斧正(反正我不认识斧正是什么意思)

 

转载于:https://www.cnblogs.com/handsome-zyc/p/11250401.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值