vijos-1754 最优贸易

来源:互联网 发布:威海 淘宝电商培训 编辑:程序博客网 时间:2024/06/02 09:40

题意:

给出一个有向图,每个点有个权值;

求从起点到终点的路径中,到某地以权值购买,再到另一个地方卖出;

所获收益的最大值;


题解:

题目中不限制路径长度和经过结点次数;

再加上数据范围的提示,很容易想到缩点;

将可以互相到达的点缩成一个,显然只要考虑这个强连通分量中的最小值和最大值就可以了;

转化成DAG后可以动态规划求解;

或者单纯的维护两个数组,mi[x]表示从1到x这个结点经过的路上的最小权值;

ma[x]表示从x到n经过的路上最大的权值;

扫一遍max(ma[x]-mi[x])就是答案;

小心一下1到不了或者到不了n的结点就可以了;


显然我写的有点麻烦。。但是思路还是比较清晰的;

2k+的代码居然1A我也是醉了(毕竟NOIP数据);


代码:


#include<stack>#include<queue>#include<vector>#include<stdio.h>#include<string.h>#include<algorithm>#define N 100100using namespace std;stack<int>st;queue<int>q;vector<int>to[N],TO[N],_TO[N];int a[N],f[N],ma[N],mi[N];int deep[N],low[N],belong[N],in[N],_in[N],tot,cnt;bool ins[N],cov[N],_cov[N];void tarjan(int x){deep[x]=low[x]=++cnt;st.push(x),ins[x]=1;int i,y;for(i=0;i<to[x].size();i++){if(!deep[y=to[x][i]])tarjan(y),low[x]=min(low[x],low[y]);else if(ins[y])low[x]=min(low[x],deep[y]);}if(deep[x]==low[x]){tot++;int k;do{k=st.top(),st.pop();ins[k]=0;belong[k]=tot;ma[tot]=max(ma[tot],a[k]);mi[tot]=min(mi[tot],a[k]);}while(k!=x);}}int main(){int n,m,i,j,k,x,y,ans;memset(mi,0x3f,sizeof(mi));scanf("%d%d",&n,&m);for(i=1;i<=n;i++)scanf("%d",a+i);for(i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&k);to[x].push_back(y);if(k-1)to[y].push_back(x);}for(i=1;i<=n;i++)if(!deep[i])tarjan(i);for(x=1;x<=n;x++){for(i=0;i<to[x].size();i++){if(belong[y=to[x][i]]!=belong[x]){TO[belong[x]].push_back(belong[y]);_TO[belong[y]].push_back(belong[x]);in[belong[y]]++;_in[belong[x]]++;}}}for(i=1;i<=tot;i++)if(!in[i])q.push(i);cov[belong[1]]=1;while(!q.empty()){x=q.front(),q.pop();for(i=0;i<TO[x].size();i++){y=TO[x][i];if(cov[x]){cov[y]=1;mi[y]=min(mi[y],mi[x]);}in[y]--;if((!in[y])&&cov[y])q.push(y);}}for(i=1;i<=tot;i++)if(!_in[i])q.push(i);_cov[belong[n]]=1;while(!q.empty()){x=q.front(),q.pop();for(i=0;i<_TO[x].size();i++){y=_TO[x][i];if(_cov[x]){_cov[y]=1;ma[y]=max(ma[y],ma[x]);}_in[y]--;if((!_in[y])&&_cov[y])q.push(y);}}for(i=1,ans=0;i<=tot;i++){if(cov[i]&&_cov[i])ans=max(ma[i]-mi[i],ans);}printf("%d",ans);return 0;}



0 0
原创粉丝点击