POJ 3767 I Wanna Go Home SPFA最短路

来源:互联网 发布:电脑快捷键软件 编辑:程序博客网 时间:2024/05/02 06:12

题意:给你N个点M条边。

接下来M行s,e,l,分别表示s-e的路程是l(无向图)

接下来输入N个数,分别表示第i个城市支持那个leader.(1和2)

问:一个人从城市1出发到城市2,到达的过程中只能有一次跨越两个支持不同leader的城市,输出最短路程,或者-1;

思路:

一开始想在SPFA里面加个限制条件,来记录城市跨越的情况,但是貌似不好写。

就DIY了一种想法。

进行2次SPFA;

第一次:

从城市1出发,将城市1 到达 第一次出现支持不同leader的城市 的dis[]记录下来。

如样例3:

553 1 2005 3 1502 5 1604 3 1704 2 1701 2 2 2 1
此时记录的dis[]值为:

dis[1]=0;

dis[2]=inf;

dis[3]=200;

dis[4]=inf;

dis[5]=inf;

第二次:

从城市2出发,将城市2到所有 相同阵营的城市(或者1,当然到达1之前必须没经过阵营变化)  的路程记为dis2[]。

同样是上面的样例:

dis1[1]=540;

dis1[2]=0;

dis1[3]=340;

dis1[4]=170;

dis1[5]=inf;

最后再枚举dis[]+dis1[]的最小值即可。若没有则输出-1;


#include <iostream>#include <cstdio>#include <algorithm>#include <string>#include <cmath>#include <cstring>#include <queue>#include <set>#include <vector>#include <stack>#include <map>#include <iomanip>#define PI acos(-1.0)#define Max 2005#define inf 1<<28using namespace std;int n,m;struct kdq{    int e,w;};vector<kdq>g[Max];int agree[Max];bool visit[Max];void spfa(int s,int *dis){    int i,j;    for(i=1; i<=n; i++)        dis[i]=inf;    dis[s]=0;    visit[s]=1;    queue<int>q;    q.push(s);    while(!q.empty())    {        int temp=q.front();        q.pop();        visit[temp]=0;        for(i=0; i<g[temp].size(); i++)        {            int v=g[temp][i].e;            int w=g[temp][i].w;            if(agree[s]!=agree[v]&&s==2)//当起点为2时,那么当阵营发生变化,并且不是变化到城市1,那么此点不处理,continue;            {                if(v!=1)                continue;            }            if(agree[s]!=agree[v]&&s==1)//更新起点1时,只经过一次阵营变化的dis[]值            {                if(dis[v]>dis[temp]+w)                dis[v]=dis[temp]+w;            }            if(dis[v]>dis[temp]+w)            {                dis[v]=dis[temp]+w;                if(!visit[v])                {                    visit[v]=1;                    q.push(v);                }            }        }    }    //for(i=1;i<=n;i++)    //cout<<dis[i]<<endl;}int main(){    int i,j,k,l,a,b,c;    while(scanf("%d",&n),n)    {        for(i=0; i<=n; i++)            g[i].clear();        int dis1[Max],dis2[Max];        scanf("%d",&m);        for(i=0; i<m; i++)        {            scanf("%d%d%d",&a,&b,&c);            kdq k;            k.e=b;            k.w=c;            g[a].push_back(k);            k.e=a;            g[b].push_back(k);        }        for(i=1; i<=n; i++)            scanf("%d",&agree[i]);        spfa(1,dis1);        spfa(2,dis2);        int min=dis1[2]<dis2[1]?dis1[2]:dis2[1];        for(i=1; i<=n; i++)//更新min找出最小值        {            if(min>dis1[i]+dis2[i])                min=dis1[i]+dis2[i];        }        if(min==inf)            cout<<-1<<endl;        else            cout<<min<<endl;    }    return 0;}
水水更健康~