POJ 3268 Silver Cow Party (Dijkstra~)

http://poj.org/problem?id=3268

N只母牛(起始地点不同)要去X这个地方,给出有向图,要求求出他们到x后并且返回(不一定原路,有向图)的路程最大的母牛(算的是来回),

其中他们走到x和从x返回走的路径均是最短的。


思路:

从x到每个点的最短路径还算好求。直接Dijkstra即可

但是从每个点到x呢?

难道要n次Dijkstra?或者floyd?

不,那样效率太低了!

一个方法是进行矩阵转置,然后再来一次Dijkstra即可。

为什么这样可以?对于有向图,本来是从n个点到x的,你转置一下相当于x到n个点了。

很巧妙吧?


#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=1010;
const int INF=99999;
int map[MAXN][MAXN];
int n,m,x;
void map_reverse()
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<i;j++)
			swap(map[i][j],map[j][i]);
}

void dijkstra(int dis[])
{
	bool vis[MAXN]={0};
	int cur=x;
	vis[cur]=true;
	dis[cur]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
			if(map[cur][j]!=INF && map[cur][j] +dis[cur] < dis[j])
				dis[j]=map[cur][j] +dis[cur];

		int mini=INF;
		for(int j=1;j<=n;j++)
			if(!vis[j] && dis[j] < mini)
				mini=dis[cur=j];

		vis[cur]=true;
	}

}
int main()
{

	while(~scanf("%d%d%d",&n,&m,&x))
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
				map[i][j]=INF;
		}

		for(int i=0;i<m;i++)
		{
			int a,b,t;
			scanf("%d%d%d",&a,&b,&t);
			map[a][b]=t;
		}

		int dis1[MAXN],dis2[MAXN];
		for(int i=1;i<=n;i++)
			dis1[i]=dis2[i]=INF;

		dijkstra(dis1);
		map_reverse();
		dijkstra(dis2);

		int ans=-1;
		for(int i=1;i<=n;i++)
		{
			if(dis1[i]==INF || dis2[i]==INF)
				continue;

			int temp=dis1[i]+dis2[i];
			if(temp > ans)
				ans=temp;
		}

		printf("%d\n",ans);
	}

	return 0;
}


你可能感兴趣的:(ACM,poj,图,最短路,dijkstra)