您的位置:首页 > 编程语言 > Go语言

poj 3767 I Wanna Go Home

2012-03-30 10:38 344 查看
题目链接:http://poj.org/problem?id=3767

核心算法 Dijkstra
大意:N个城市,城市编号为1,2,3,……N
M条路,路为双向路。 提供每条路的长度及端点城市编号,每两个城市之间直接连通的路最多一条。
这N个城市分为两个集合,部分属于集合1,部分属于集合2,提供每个城市所属的集合,
现要求从城市1出发去城市2,要求途径的路中最多出现一条其两端城市不属于同一个集合
的路,求出符合该条件下的从城市1到城市2的最短路,若不存在符合条件的路,输出-1
注:数据中城市1必定属于集合1,城市2必定属于集合2

分析:由于城市1与城市2所属的集合固定,故在路径中必定有一条而且只能有一条路从属于集合
1的城市出发进入城市2,而定不会出现从集合2走向集合1的城市。
如此,M条路中凡是连接属于不同集合的城市的路为单向路,只能从集合1中的城市走向集合2,连接相同集合的为双向路。
在此基础上用Dijkstra算法求最短路即可。

主要在于建图。昨天比赛刚开始做时用的方法是,标记然后两次Dijkstra,结果老是wa,然后就想在建图时处理下。只用一次就可以了。这题6次才过,竟然两次CE 太不小心了。

比较郁闷的是其他队,用BFS就过了 ,数据太水。

View Code

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX=605;
int map[MAX][MAX];
int vist[MAX];
int dist[MAX];
struct ss{
int x,y,z;
}edge[10005];
int num[MAX],ans;
int n,m;
const int INF=99999999;
void dij( )
{
int i,j,v,ma;
memset(vist,0,sizeof(vist));
for(i=1;i<=n;i++)
dist[i]=map[1][i];
vist[1]=1;
dist[1]=0;
for(i=1;i<n;i++)
{
ma=INF;
for(j=1;j<=n;j++)
if(!vist[j]&&dist[j]<ma)
{
ma=dist[j];
v=j;
}
if(ma==INF)break;
vist[v]=1;
for(j=1;j<=n;j++)
{
if(!vist[j]&&dist[j]>map[v][j]+dist[v])
dist[j]=map[v][j]+dist[v];
}

}
}

int main()
{
int i,j;
while(scanf("%d",&n)&&n)
{
scanf("%d",&m);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
map[i][j]=INF;
dist[i]=INF;
}
map[i][i]=0;
}
ans=INF;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);

}
for(i=1;i<=n;i++)
scanf("%d",&num[i]);

for(i=1;i<=m;i++)
{
if(num[edge[i].x]==num[edge[i].y])
{
map[edge[i].x][edge[i].y]=map[edge[i].y][edge[i].x]=edge[i].z;
}
else {
if(num[edge[i].x]==1)
map[edge[i].x][edge[i].y]=edge[i].z;
else map[edge[i].y][edge[i].x]=edge[i].z;
}
}
dij();

ans=dist[2];
if(ans>=INF)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: