nyoj 247 虚拟的城市之旅
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=247
这是第三届省赛的题,一直不会做,今天看了下其他的博客感觉挺好理解的,就照着写了下。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int MAXM=1000500; 7 const int MAXN=100100; 8 struct node{ 9 int y,next; 10 }edge[MAXM],edge1[MAXM]; 11 int visit[MAXN],dfn[MAXN],low[MAXN]; 12 int head[MAXN],head1[MAXN],id[MAXN],key[MAXN]; 13 int max_pre[MAXN],min_pre[MAXN],stack[MAXN]; 14 int ideax,res,N,num,top,n,s,t; 15 void init() 16 { 17 memset(head,-1,sizeof(head)); 18 memset(head1,-1,sizeof(head1)); 19 memset(dfn,0,sizeof(dfn)); 20 memset(low,0,sizeof(low)); 21 memset(visit,0,sizeof(visit)); 22 res=N=ideax=top; 23 } 24 void add(int x,int y)//建图 25 { 26 edge[N].y=y; 27 edge[N].next=head[x]; 28 head[x]=N++; 29 } 30 int max(int x,int y) 31 { 32 if(x>y)return x; 33 else return y; 34 } 35 int min(int x,int y) 36 { 37 if(x>y)return y; 38 else return x; 39 } 40 void DFS(int u) 41 { 42 int i,v,maxmax,minmin; 43 dfn[u]=low[u]=ideax++; 44 visit[u]=1; 45 stack[++top]=u; 46 for(i=head[u];i!=-1;i=edge[i].next) 47 { 48 v=edge[i].y; 49 if(!dfn[v]) 50 { 51 DFS(v); 52 low[u]=min(low[u],low[v]); 53 } 54 else if(visit[v]&&dfn[v]<low[u]) 55 low[u]=dfn[v]; 56 } 57 58 if(dfn[u]==low[u]) 59 { 60 res++; 61 maxmax=0,minmin=1000; 62 do{ 63 v=stack[top--]; 64 visit[v]=0; 65 if(v==1)s=res; 66 if(v==n)t=res; 67 id[v]=res; 68 if(key[v]>maxmax)maxmax=key[v]; //在一个连通分量里边求最大值 69 if(key[v]<minmin)minmin=key[v]; //在一个连通分量里边求最小值 70 }while(v!=u); 71 max_pre[res]=maxmax; 72 min_pre[res]=minmin; 73 } 74 } 75 void tarjan() //求强连通 76 { 77 int i; 78 for(i=1;i<=n;i++) 79 if(!dfn[i]) 80 DFS(i); 81 } 82 83 int solve() 84 { 85 int i,u,v,j; 86 tarjan(); 87 num=0; 88 for(i=1;i<=n;i++) //对缩点建图 89 for(j=head[i];j!=-1;j=edge[j].next) 90 if(id[i]!=id[edge[j].y]){ 91 edge1[num].y=id[edge[j].y]; 92 edge1[num].next=head1[id[i]]; 93 head1[id[i]]=num++; 94 } 95 memset(key,0,sizeof(key)); 96 queue<int>Q; 97 Q.push(s); 98 while(!Q.empty()) 99 { 100 u=Q.front(); 101 Q.pop(); 102 if(u==t)break; 103 for(j=head1[u];j!=-1;j=edge1[j].next) 104 { 105 v=edge1[j].y; 106 min_pre[v]=min(min_pre[u],min_pre[v]); //到目前为止最小的买入价 107 key[v]=max(key[u],max_pre[v]-min_pre[v]);//找可以赚的最大钱数 108 Q.push(v); 109 } 110 } 111 return key[t]; 112 } 113 int main() 114 { 115 int i,m,x,y,z; 116 while(scanf("%d%d",&n,&m)!=EOF) 117 { 118 init(); 119 for(i=1;i<=n;i++) 120 scanf("%d",&key[i]); 121 for(i=1;i<=m;i++) 122 { 123 scanf("%d%d%d",&x,&y,&z); 124 if(z==1)add(x,y); 125 else {add(x,y);add(y,x);} 126 } 127 printf("%d\n",solve()); 128 } 129 return 0; 130 }