Luogu P1073 最优贸易【最短路/建反图】 By cellur925
2018-08-14 23:02
302 查看
这么经典的题目,还是看了lyd的题解....唉难过。
一句话题意:在一张点有全都的图上找一条从1到n的路径,存在两个点p,q(p<q),使val[q]-val[p]最大。
给出的图是既有双向又有单向的混合图,考虑像普通的方法一样建图。除此之外,再在一个新邻接表中建原图的反图(边方向相反)。
为什么要这样做?
考虑分别自起点到终点和自终点到起点遍历,计算出f[]和d[],其中f[i]表示从1到i的路径中经过的最小的点权,d[i]表示从n到i的路径中经过的最大点权。(想一想,为什么?)
于是我们就可以枚举断点X,使d[x]-f[x]最大。保证了1能走到n,即路径的连贯(联通)性。
code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 #define maxn 100090 6 #define maxm 500090 7 8 using namespace std; 9 10 int n,m,totp,totn,ans; 11 int headp[maxn],headn[maxn],val[maxn],f[maxn],d[maxn],vis[maxn]; 12 struct node{ 13 int to,next; 14 }; 15 node edge_posi[maxm*4],edge_nega[maxm*4]; 16 17 void add_posi(int x,int y) 18 { 19 edge_posi[++totp].to=y; 20 edge_posi[totp].next=headp[x]; 21 headp[x]=totp; 22 } 23 24 void add_nega(int x,int y) 25 { 26 edge_nega[++totn].to=y; 27 edge_nega[totn].next=headn[x]; 28 headn[x]=totn; 29 } 30 31 void spfa_posi() 32 { 33 queue<int>q; 34 memset(d,0x3f,sizeof(d)); 35 q.push(1);d[1]=val[1];vis[1]=1; 36 while(!q.empty()) 37 { 38 int x=q.front(); 39 q.pop();vis[x]=0; 40 for(int i=headp[x];i;i=edge_posi[i].next) 41 { 42 int y=edge_posi[i].to; 43 if(min(d[x],val[y])<d[y]) 44 { 45 d[y]=min(d[x],val[y]); 46 if(!vis[y]) q.push(y),vis[y]=1; 47 } 48 } 49 } 50 } 51 52 void spfa_nega() 53 { 54 queue<int>q; 55 memset(vis,0,sizeof(vis)); 56 memset(f,128,sizeof(f)); 57 q.push(n);d =val ;vis =1; 58 while(!q.empty()) 59 { 60 int x=q.front(); 61 q.pop();vis[x]=0; 62 for(int i=headn[x];i;i=edge_nega[i].next) 63 { 64 int y=edge_nega[i].to; 65 if(max(f[x],val[y])>f[y]) 66 { 67 f[y]=max(f[x],val[y]); 68 if(!vis[y]) q.push(y),vis[y]=1; 69 } 70 } 71 } 72 } 73 74 int main() 75 { 76 scanf("%d%d",&n,&m); 77 for(int i=1;i<=n;i++) scanf("%d",&val[i]); 78 for(int i=1;i<=m;i++) 79 { 80 int x=0,y=0,opt=0; 81 scanf("%d%d%d",&x,&y,&opt); 82 if(opt==1) 83 { 84 add_posi(x,y); 85 add_nega(y,x); 86 } 87 else if(opt==2) 88 { 89 add_posi(x,y);add_posi(y,x); 90 add_nega(y,x);add_nega(x,y); 91 } 92 } 93 spfa_posi(); 94 spfa_nega(); 95 for(int i=1;i<=n;i++) 96 ans=max(ans,f[i]-d[i]); 97 printf("%d",ans); 98 return 0; 99 }View Code
建反图的思想妙啊!
相关文章推荐
- 【图-最短路】NOIP2009最优贸易
- P1073 最优贸易 NOIP 2009 最短路
- 【NOIP2009】最优贸易 最短路
- Luogu P1073 最优贸易
- 【vijos】【建反图最短路】最优贸易
- 最优贸易 2009年NOIP全国联赛提高组(最短路)
- luogu P1073 最优贸易 NOIP2009 题解
- NOIP 2009 最优贸易 luogu1073
- 洛谷 P1073 最优贸易
- codevs 1173 最优贸易 2009年NOIP全国联赛提高组(spfa)
- P1073 最优贸易
- [NOIP2009]潜伏者,Hankson's Problem,最优贸易,靶形数独
- 最优贸易
- [noip2009]: 最优贸易
- NOIP2009提高组 最优贸易
- NOIP2009-T3 洛谷-1073 最优贸易
- codevs 1173 最优贸易
- NYOJ564 & CSU 1106 最优对称路径【记忆化搜索+最短路】
- 最优贸易(洛谷 1073)
- [Codevs] 1173 最优贸易