题目大意:给你村庄和村庄之间的距离和费用,如果这个村庄的费用可以无限小就输出UNBOUND,如果这两个村庄之间没有路就输出VOID,否则则输出在满足最小费用下的最短路。
算法思路:判断村庄费用无限小其实就是判断在所给的两个村庄a,b之间是否存在负环,注意全图存在负环但这两个村庄之间不存在负环的情况要考虑啊!因此我们要判断一下如果存在任意一个入队次数>n的点与b连通,或者本身b的入队次数就>n就说明a与b之间存在负环,输出UNBOUND,如果dist[b]==INF就说明a到不了b就输出VOID,否则输出最小费用和最小距离即可。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define INF 0x3f3f3f3f int n,m,a,b,e,num1,num2,num3,num4,num5; int head[2005],next[10050],dist[2005],dist2[2005]; bool visited[2005]; char str[50]; int num[2005]; bool flag; typedef struct Edge { int u; int v; int c; int value; }; Edge edges[10050]; void addNode(int u,int v,int c,int value) { //注意见图的时候这里要进行判断,某个点的单链表中如果有多条边的话,我们只取费用最小的那一个点组成单链表 if(head[u]!=-1&&value>edges[head[u]].value) return; if(head[u]!=-1&&value<edges[head[u]].value) head[u]=-1; edges[e].u=u; edges[e].v=v; edges[e].c=c; edges[e].value=value; next[e]=head[u]; head[u]=e++; } bool relax(int u,int v,int c,int value) { if(dist2[v]>dist2[u]+value||dist2[v]==dist2[u]+value&&dist[v]>dist[u]+c) { dist2[v]=dist2[u]+value; dist[v]=dist[u]+c; return true; } return false; } bool spfa(int src) { memset(visited,false,sizeof(visited)); memset(num,0,sizeof(num)); for(int i=0;i<n;i++) { dist[i]=INF; dist2[i]=INF; } dist[src]=0; dist2[src]=0; queue<int>que; visited[src]=true; que.push(src); while(!que.empty()) { int q=que.front(); que.pop(); visited[q]=false; for(int i=head[q];i+1;i=next[i]) { if(relax(q,edges[i].v,edges[i].c,edges[i].value)&&!visited[edges[i].v]) { if(++num[edges[i].v]>n) return false; visited[edges[i].v]=true; que.push(edges[i].v); } } } return true; } void dfs(int x,int y) { visited[x]=true; if(x==y)//如果存在num[x]>n的点与结束点相连接的话,就标记 { flag=true; return; } for(int i=head[x];i+1;i=next[i]) { if(!visited[edges[i].v]) { dfs(edges[i].v,y); } } } int main() { while(~scanf("%d%d%d%d",&n,&m,&a,&b)) { e=0;flag=false; memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); memset(edges,0,sizeof(edges)); for(int i=0; i<m; i++) { int sum=0; int nn=0; bool isfu=false; scanf("%s",str); sscanf(str,"(%d,%d,%d[%d]%d)",&num1,&num2,&num3,&num4,&num5); addNode(num1,num2,num4,num3); addNode(num2,num1,num4,num5); } bool ok=spfa(a); for(int i=0;i<n;i++) { if(num[i]>n) { memset(visited,false,sizeof(visited)); flag=false; dfs(i,b); if(flag) break; } } if(dist[b]==INF) { printf("VOID\n"); } else { if(ok) printf("%d %d\n",dist2[b],dist[b]); else { if(flag||num[b]>n) printf("UNBOUND\n"); else printf("%d %d\n",dist2[b],dist[b]); } } } }