poj 3114 强连通+缩点+记忆化搜索

题意大致是这样的:在一个有向图里面,在同一个强连通分量里面的点之间的消费为0,不在同一个强连通分量的点之间是有消费的,问从一个点到另一个点的最小消费。

很显然在同一个强连通分量的点可以缩为一个点,然后重新构图结果肯定是一棵树。从始点到终点的最小消费可以用记忆化搜索来求解。

代码如下:

#include<iostream>

#include<cstring>

#include<stack>

using namespace std;

#define MAX_INT 1234567890

struct node

{

	int v;

	int value;

	int next;

};

stack <int> S;

int pre[501],low[501],sc[501],cnt0,cnt1;

int head1[501],head2[501],memory[501],n,N,M;

node edge1[250001],edge2[250001];

int Tarjan(int i)

{

    int j,min,e;

	pre[i]=cnt0++; low[i]=pre[i]; min=pre[i];

	S.push(i);

	for(j=head1[i];j!=0;j=edge1[j].next)

	{

		if(pre[edge1[j].v]==-1) Tarjan(edge1[j].v);

		if(min>low[edge1[j].v]) min=low[edge1[j].v];

	}

	if(min<low[i]) {low[i]=min; return 0;}

	do

	{

        e=S.top(),S.pop(); sc[e]=cnt1; low[e]=n;

	} while(e!=i);

	cnt1++;

	return 0;

}

int CGraph(int n)

{

	int i,j;

	for(i=1;i<=n;i++)

		for(j=head1[i];j;j=edge1[j].next)

			if(sc[i]!=sc[edge1[j].v]) 

			{

				node e={sc[edge1[j].v],edge1[j].value,0};

				edge2[M]=e;

				edge2[M].next=head2[sc[i]];

				head2[sc[i]]=M++;

			}

	return 0;

}

int dfs(int s,int t)

{

	int i,k,min=MAX_INT;

	if(memory[s]) 

		return memory[s];

	if(s==t)

		return 0;

    for(i=head2[s];i;i=edge2[i].next)

	{

        k=dfs(edge2[i].v,t);

		min=(min>k+edge2[i].value) ? k+edge2[i].value:min;

	}

	memory[s]=min;

	return memory[s];

}

int main()

{

	int i,k,m,s,t,cost,start,end;

	while(scanf("%d%d",&n,&m)!=EOF && n)

	{

		N=M=1;

		memset(head1,0,sizeof(head1));

		for(i=0;i<m;i++)

		{

			scanf("%d%d%d",&s,&t,&cost);

			node e={t,cost,0};

			edge1[N]=e;

			edge1[N].next=head1[s];

			head1[s]=N++;

		}

		for(i=1;i<=n;i++) pre[i]=-1;

		memset(sc,0,sizeof(sc));

		for(cnt0=cnt1=1,i=1;i<=n;i++)

			if(pre[i]==-1) Tarjan(i);

		memset(head2,0,sizeof(head2));

		CGraph(n);

		memset(memory,0,sizeof(memory));

		cin>>k;

		while(k--)

		{

			cin>>start>>end;

			memset(memory,0,sizeof(memory));

			if(sc[start]==sc[end])

			{

				cout<<"0"<<endl;

				continue;

			}

			s=dfs(sc[start],sc[end]);

			if(s>=MAX_INT) 

				cout<<"Nao e possivel entregar a carta"<<endl;

			else 

				cout<<s<<endl;

		}

		cout<<endl;

	}

	return 0;

}

你可能感兴趣的:(poj)