hdu 1874 畅通工程续-spfa

来源:互联网 发布:ubuntu 安装 分辨率 编辑:程序博客网 时间:2024/05/22 18:39
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#define M 100000#define MAX 0x3f3f3fusing namespace std;struct Edge{int from,to,val,next;};Edge edge[MAX];queue<int> q;int head[220];int dist[220];int vis[220];int n,m;int edgenum;void addedge(int u,int v,int w){Edge E={u,v,w,head[u]};//这个定义是可以的,从别人那里借鉴来的 edge[edgenum]=E;head[u]=edgenum++;//printf("%d\n",edge[edgenum-1].next);//printf("%d\n",head[u]);//return 0;}void spfa(int s,int t){//printf("%d\n",M);//printf("%d\n",dist[2]);int u,v;int i;dist[s]=0;q.push(s);vis[s]=1;while(!q.empty()){u=q.front();q.pop();vis[u]=0;//每次出队列之后要把此点标记为未访问 for(i=head[u];i!=-1;i=edge[i].next){//printf("%d\n",i);v=edge[i].to;if(dist[v]>dist[u]+edge[i].val){dist[v]=dist[u]+edge[i].val;//printf("%d\n",dist[v]);if(!vis[v])//注意要判断此点是否已在队列内{q.push(v);vis[v]=1; //标记此点已在队列内 }}}}if(dist[t]>=10000)printf("-1\n");elseprintf("%d\n",dist[t]);//return 0;}int main(){int i;int a,b,c;int s,t;while(scanf("%d%d",&n,&m)!=EOF){memset(head,-1,sizeof(head));for(i=0;i<n;i++)dist[i]=M;//用这个也不会费多少时间的 /*此处最好不要用#define INF 0x3f3f3f3f memset(dist,INF,sizeof(dist));  因为会超过int型的存储范围,可以试着输出dist[2]的值于INF的值进行比较,是不相等的而且题目当中说X的取值范围不大于10000,所以可以定义一个100000来初始化dist[220]; */memset(vis,0,sizeof(vis));edgenum=0;for(i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);addedge(a,b,c);addedge(b,a,c);/*这里为什么要这样输入就跟spfa的算法本身有关了,举个例子:数据是  3 1       0 1 1       1 2这个是什么意思可以去看题目的 ,将这些数据带入程序进行模拟,那么我们可以知道第一步:点1对点2进行更新 ,此时点2进入队列 第二步:点2会对点1进行更新差不多相当于map[1][2]=map[2][1],我们知道第一步是使用map[1][2],第二步是使用map[2][1]所以在输入的时候要正反个输入一次 不过我们此处用的是邻接表,输入之后的数据是这样的0 1 1 edge[0]=E  edge[0].next=E.head[0]=-1  edgenum=1;   head[0]=01 0 1 edge[1]=E  edge[1].next=E.head[1]=-1  edgenum=2;   head[1]=1;此处注意E.head[]跟head[]是不相等的 正面和反面的输入的val值是不变的,所以在进行正反更新的时候是不会影响的,这个跟邻接表的性质有关我觉得他们之间的连接与应用真的是太巧妙了 */}scanf("%d%d",&s,&t);spfa(s,t);}return 0;}

0 0