原文:http://blog.acmj1991.com/?p=632
题意:nyoj 247 虚拟城市之旅
思路:强连通缩点
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define maxN 100100
#define maxM 1000100
struct point{
int v,cow,next;
}po[maxM],map[maxM];
int num,N,head[maxN],key[maxN],head1[maxN];
int s,t,top,res,inde,stack[maxN],dfn[maxN],low[maxN],id[maxN],vis[maxN],max_pre[maxN],min_pre[maxN];
void add(int u,int v)
{
po[num].v=v;
po[num].next=head[u];
head[u]=num++;
}
void init()
{
memset(head,-1,sizeof(head));
memset(head1,-1,sizeof(head1));
memset(id,0,sizeof(id));
memset(vis,0,sizeof(vis));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
top=res=num=0;
inde=1;
}
void dfs(int u)
{
int v;
low[u]=dfn[u]=inde++;
stack[++top]=u;
vis[u]=1;
for(int i=head[u];i!=-1;i=po[i].next){
v=po[i].v;
if(!dfn[v]){
dfs(v);
low[u]=min(low[u],low[v]);
}else if(vis[v]&&dfn[v]<low[u])
low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
int max_p=0,min_p=1110;
res++;
do{
v=stack[top--];
if(v==1)s=res;
if(v==N)t=res;
id[v]=res;
vis[v]=0;
max_p=max(max_p,key[v]);
min_p=min(min_p,key[v]);
}while(v!=u);
max_pre[res]=max_p;
min_pre[res]=min_p;
}
}
void tarjan()
{
for(int i=1;i<=N;i++)
if(!dfn[i])
dfs(i);
}
void solve()
{
tarjan();num=0;
for(int j=1;j<=N;j++)
for(int i=head[j];i!=-1;i=po[i].next)
if(id[j]!=id[po[i].v]){
map[num].v=id[po[i].v];
map[num].next=head1[id[j]];
head1[id[j]]=num++;
}
queue<int>q;
q.push(s);
int minn=1000;
memset(key,0,sizeof(key));
while(!q.empty()){
int u=q.front();q.pop();
if(u==t)break;
for(int i=head1[u];i!=-1;i=map[i].next){
int v=map[i].v;
min_pre[v]=min(min_pre[v],min_pre[u]);
key[v]=max(key[u],max_pre[v]-min_pre[v]);
q.push(v);
}
}
printf("%d\n",key[t]);
}
int main()
{
int n,m,u,v,d;
while(~scanf("%d%d",&N,&m)){
init();
memset(head,-1,sizeof(head));
for(int i=1;i<=N;i++)scanf("%d",&key[i]);
while(m--){
scanf("%d%d%d",&u,&v,&d);
if(d==1)add(u,v);
else{
add(u,v);
add(v,u);
}
}
solve();
}
return 0;
}