这两天做题被虐的难受..老是莫名其妙的不通过 ..也一直没更博
写了这道题,AC了,算是找回点自信,还是在机试指南的提示下做出来的
嗯,看下题目吧
—————————————————————————————————————————————————————
-
题目描述:
-
The country is facing a terrible civil war----cities in the country are divided into two parts supporting different leaders. As a merchant, Mr. M does not pay attention to politics but he actually knows the severe situation, and your task is to help him reach home as soon as possible.
"For the sake of safety,", said Mr.M, "your route should contain at most 1 road which connects two cities of different camp."
Would you please tell Mr. M at least how long will it take to reach his sweet home?
-
输入:
-
The input contains multiple test cases.
The first line of each case is an integer N (2<=N<=600), representing the number of cities in the country.
The second line contains one integer M (0<=M<=10000), which is the number of roads.
The following M lines are the information of the roads. Each line contains three integers A, B and T, which means the road between city A and city B will cost time T. T is in the range of [1,500].
Next part contains N integers, which are either 1 or 2. The i-th integer shows the supporting leader of city i.
To simplify the problem, we assume that Mr. M starts from city 1 and his target is city 2. City 1 always supports leader 1 while city 2 is at the same side of leader 2.
Note that all roads are bidirectional and there is at most 1 road between two cities.
Input is ended with a case of N=0.
-
输出:
-
For each test case, output one integer representing the minimum time to reach home.
If it is impossible to reach home according to Mr. M's demands, output -1 instead.
-
样例输入:
-
2 1 1 2 100 1 2 3 3 1 2 100 1 3 40 2 3 50 1 2 1 5 5 3 1 200 5 3 150 2 5 160 4 3 170 4 2 170 1 2 2 2 1 0
-
样例输出:
-
100 90 540
还有点无关话题需要注意:当需要输出路径的时候,定义一个pre[N]数组,在更新邻边的时候,存放更新结点的先驱结点为当前节点,这样通过栈或队列就可以实现倒叙或顺序输出路径
代码如下:
#include <stdio.h>
#include <vector>
using namespace std;
struct E{
int start;
int next;
int cost;
}buff[10001];
vector<E> edge[10010];
int Cost[601];
bool mark[601];
int camp[601];
int main(int argc, char** argv) {
int N,M;
while(scanf("%d",&N)!=EOF)
{
if(N==0) break;
scanf("%d",&M);
int i;
//初始化vector
for(i=1;i<=N;i++) edge[i].clear();
//输入道路信息,暂存在数组里
for(i=1;i<=M;i++)
{
scanf("%d%d%d",&buff[i].start,&buff[i].next,&buff[i].cost);
}
//输入阵营信息
for(i=1;i<=N;i++)
{
scanf("%d",&camp[i]);
}
//正式录入边信息
for(i=1;i<=M;i++)
{
int a=buff[i].start;
int b=buff[i].next;
E tmp;
tmp.cost=buff[i].cost;
//如果是同一阵营则可双向,录入两次
if(camp[a]==camp[b])
{ tmp.start=a;
tmp.next=b;
edge[a].push_back(tmp);
tmp.start=b;
tmp.next=a;
edge[b].push_back(tmp);
}
//如果不是同一阵营,只录入从阵营1->2
if(camp[a]!=camp[b])
{
if(camp[a]==1){
tmp.start=a;
tmp.next=b;
edge[a].push_back(tmp);
}
else
{
tmp.start=b;
tmp.next=a;
edge[b].push_back(tmp);
}
}
}//录入结束
//初始化Cost
for(i=1;i<=N;i++)
{
Cost[i]=-1;
mark[i]=false;
}
int newP=1;
Cost[1]=0;
mark[1]=true;
//只循环N-1次就可以了
for(i=1;i<N;i++)
{
//更新新成员的临边信息
int j;
for(j=0;j<edge[newP].size();j++)
{
int t =edge[newP][j].next;
int c=edge[newP][j].cost;
//如果已经在集合中,则跳过
if(mark[t]==true) continue;
//如果距离临点的距离可更新
if(Cost[t]==-1||Cost[t]>Cost[newP]+c)
{
Cost[t]=Cost[newP]+c;
}
}
//选取下一个新点
int min=123123123;
for(j=1;j<=N;j++)
{
if(mark[j]==true) continue;
if(Cost[j]==-1) continue;
if(Cost[j]<min)
{
min=Cost[j];
newP=j;
}
}
mark[newP]=true;
}//大for循环
if(Cost[2]!=-1)
printf("%d\n",Cost[2]);
else
printf("%d\n",-1);
}//最外层循环
return 0;
}