【tarjan+SPFA】BZOJ1179-[Apio2009]Atm

【题目大意】

给出一张有点权的有向图,已知起点和可以作为终点的一些点,问由起点出发,每条边和每个点可以经过任意多次,经过点的权值总和最大为多少。

【思路】

由于可以走任意多次,显然强连通分量可以缩点。然后就是一张DAG图,跑SPFA最长路就好了。

听说Dijkstra写最长路会发生一些奇特的化学反应并且炸掉,还没想清楚姑且笔记一下。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int MAXN=500000+50;
  4 struct edge
  5 {
  6     int to,len;
  7 };
  8 int n,m,s,p,money[MAXN],bar[MAXN],u[MAXN],v[MAXN];
  9 vector<int> E[MAXN];
 10 vector<edge> rE[MAXN];
 11 stack<int> S;
 12 queue<int> que;
 13 int instack[MAXN],low[MAXN],dfn[MAXN],sum[MAXN],col[MAXN],cnt,tot;
 14 int dis[MAXN],inque[MAXN];
 15 
 16 void addedge(int u,int v)
 17 {
 18     E[u].push_back(v);
 19 }
 20 
 21 void addedge2(int u,int v,int w)
 22 {
 23     rE[u].push_back((edge){v,w});
 24 }
 25 
 26 void tarjan(int x)
 27 {
 28     dfn[x]=low[x]=++cnt;
 29     instack[x]=1;
 30     S.push(x);
 31     for (int i=0;i<E[x].size();i++)
 32     {
 33         int to=E[x][i];
 34         if (!instack[to])
 35         {
 36             tarjan(to);
 37             low[x]=min(low[x],low[to]); 
 38         }
 39         else if (instack[to]==1)
 40         {
 41             low[x]=min(low[x],dfn[to]);
 42         }
 43     }
 44     
 45     if (dfn[x]==low[x])
 46     {
 47         tot++;
 48         int tmp;
 49         do
 50         {
 51             tmp=S.top();S.pop();
 52             sum[tot]+=money[tmp];
 53             col[tmp]=tot;
 54             instack[tmp]=2;
 55         }while (tmp!=x);
 56     }
 57 }
 58 
 59 void spfa(int start)
 60 {
 61     memset(inque,0,sizeof(inque));
 62     for (int i=1;i<=tot;i++) dis[i]=0;
 63     dis[start]=sum[start];
 64     inque[start]=1;
 65     que.push(start);
 66     while (!que.empty())
 67     {
 68         int head=que.front();que.pop();
 69         inque[head]=0;
 70         for (int i=0;i<rE[head].size();i++)
 71         {
 72             int to=rE[head][i].to,len=rE[head][i].len;
 73             if (dis[to]<dis[head]+len)
 74             {
 75                 dis[to]=dis[head]+len;
 76                 if (!inque[to])
 77                 {
 78                     inque[to]=1;
 79                     que.push(to);
 80                 }
 81             }
 82         }
 83     }
 84 }
 85 
 86 void rebuild()
 87 {
 88     for (int i=1;i<=m;i++)
 89         if (col[u[i]]!=col[v[i]]) addedge2(col[u[i]],col[v[i]],sum[col[v[i]]]);
 90 }
 91 
 92 void init()
 93 {
 94     scanf("%d%d",&n,&m);
 95     for (int i=1;i<=m;i++)
 96     {
 97         scanf("%d%d",&u[i],&v[i]);
 98         addedge(u[i],v[i]);
 99     }
100     for (int i=1;i<=n;i++) scanf("%d",&money[i]);
101     memset(bar,0,sizeof(bar));
102     scanf("%d%d",&s,&p);
103     for (int i=1;i<=p;i++)
104     {
105         int nowp;
106         scanf("%d",&nowp);
107         bar[nowp]=1;
108     }
109 } 
110 
111 void solve()
112 {
113     cnt=tot=0;
114     memset(instack,0,sizeof(instack));
115     for (int i=1;i<=n;i++)
116         if (!instack[i]) tarjan(i);
117     rebuild();
118     spfa(col[s]);
119     int ans=-1;
120     for (int i=1;i<=n;i++)
121         if (bar[i]) ans=max(ans,dis[col[i]]);
122     printf("%d",ans);
123 }
124 
125 int main()
126 {
127     init();
128     solve();
129     return 0;
130 }

 

转载于:https://www.cnblogs.com/iiyiyi/p/6070493.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
校园失物招领系统管理系统按照操作主体分为管理员和用户。管理员的功能包括字典管理、论坛管理、公告信息管理、失物招领管理、失物认领管理、寻物启示管理、寻物认领管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 校园失物招领系统管理系统可以提高校园失物招领系统信息管理问题的解决效率,优化校园失物招领系统信息处理流程,保证校园失物招领系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 ,管理员权限操作的功能包括管理公告,管理校园失物招领系统信息,包括失物招领管理,培训管理,寻物启事管理,薪资管理等,可以管理公告。 失物招领管理界面,管理员在失物招领管理界面中可以对界面中显示,可以对失物招领信息的失物招领状态进行查看,可以添加新的失物招领信息等。寻物启事管理界面,管理员在寻物启事管理界面中查看寻物启事种类信息,寻物启事描述信息,新增寻物启事信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值