题目连接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=247
分析:为了解决环的问题,可以进行强连通缩点建图,可以记录一下每个强连通中商品能达到的最大值和最小值,然后在缩过点的无环图上搜索,在搜索路径上不断更新商品最小值与最大差值,如果能到达终点更新最大利润。
参考代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define NN 100005
#define MM 1000005
#define CLR(arr,v) memset(arr,v,sizeof(arr))
int Connect[NN],Price[NN],ConnectNum,H[NN],Num[MM],Next[MM],Low[NN],First[NN],Stack[NN],top;
bool InStack[NN];
int Min[NN],Max[NN];
int pos,ind,result;
int h[NN],num[MM],nex[MM];
void Clear()
{
result = 0;
pos = 0;
CLR(h,-1);
CLR(H,-1); CLR(InStack,0);
CLR(Max,-1);
fill(Min,Min+NN,10000);
}
void add1(int u,int v)
{
Num[pos] = v;
Next[pos] = H[u];
H[u] = pos++;
}
void add2(int u,int v)
{
num[pos] = v;
nex[pos] = h[u];
h[u] = pos++;
}
void Dfs(int cur)
{
First[cur] = Low[cur] = ++ind;
Stack[top++] = cur;
InStack[cur] = true;
for(int i = H[cur];i != -1;i = Next[i])
{
if(!First[ Num[i] ])
{
Dfs(Num[i]);
Low[cur] = min(Low[cur],Low[ Num[i] ]);
}
else if(InStack[ Num[i] ])
Low[cur] = min(Low[cur],First[ Num[i]]);
}
if(Low[cur] == First[cur])
{
int s;
ConnectNum++;
do{
s = Stack[--top];
InStack[s] = false;
Connect[s] = ConnectNum;
Min[ConnectNum] = min(Min[ConnectNum],Price[s]);
Max[ConnectNum] = max(Max[ConnectNum],Price[s]);
}while(s != cur);
}
}
int Tarjan(int n)
{
ConnectNum = 0;
ind = top = 0;
CLR(First,0);
CLR(Low,0);
for(int i = 1;i <= n;++i){
if(!First[i]) Dfs(i);}
return ConnectNum;
}
void Builtgraph(int n)
{
pos = 0;
for(int i = 1;i <= n;++i)
for(int j = H[i];j != -1;j = Next[j])
if(Connect[i] != Connect[ Num[j] ])
add2(Connect[i],Connect[ Num[j] ]);
}
void dfs(int cur,int n,int Mnum,int MaxNum)
{
int maxres = 0;
if(cur == n) {result = max(result,MaxNum);return ;}
for(int i = h[cur];i != -1;i = nex[i])
{
maxres = max(MaxNum,max(Max[ num[i] ] - Mnum,Max[ num[i] ] - Min[ num[i] ]));
dfs(num[i],n,min(Mnum,Min[ num[i] ]),maxres);
}
}
int main()
{
//freopen("2.txt","r",stdin);
int m,n; int T = 1;
while(scanf("%d%d",&n,&m) != EOF)
{
Clear();
int z,b,e;
for(int i = 1;i <= n;++i)
scanf("%d",&Price[i]);
for(int i = 0;i < m;++i)
{
scanf("%d%d%d",&b,&e,&z);
add1(b,e);
if(z == 2) add1(e,b);
}
// T++;if(T >= 4) continue;
Tarjan(n);
Builtgraph(n);
dfs(Connect[1],Connect[n],Min[ Connect[1] ],Max[ Connect[1] ] - Min [ Connect[1] ]);
printf("%d\n",result);
}
return 0;
}