计蒜客-百度地图导航
题意:中文题意;
解题思路:这道题麻烦就在于城市群这个东西,所以我们首先就得解决掉这个,最开始思路(建立虚拟源点和汇点,然后有1的城市群和有5的城市群分别连,然后就发现了连样例都对不上,正好发现了如果s,t在同一群内,会造成城市群内的点任意到达这种情况),明显需要拆点,将一个城市群拆成两个点,一个入点,一个出点,如果两个城市群之间有路径,那么x出连接y入,y出连接x入,城市群内的点分别与出点连接权值为0的边,入点分别与群内的点连接一个边权为0的边;
实际上就是我们对城市群处理一下,因为暴力建边不行,我们只能想办法将两个城市群连接起来,那么建立每个城市群建立两个虚拟的城市群源汇点就行了;这样,通过这两个点可以让两个城市群相连。
记得long long 和无解的情况;
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<queue> #include<cstring> #define maxn 1000500 #define ll long long const ll inf=1e15; using namespace std; struct node { ll num; ll dist; node(ll _num=0,ll _dist=0):num(_num),dist(_dist){} friend bool operator<(node a,node b) { return a.dist>b.dist; } }; struct Edge { ll next; ll to; ll w; }edge[maxn]; ll n,m,k,m1,m2,x,y,w,q; ll s,t; ll head[maxn]; ll cnt; ll dist[maxn]; void add(ll u,ll v,ll w) { edge[cnt].next=head[u]; edge[cnt].to=v; edge[cnt].w=w; head[u]=cnt++; } void dij(ll u) { for(ll i=1;i<=maxn;i++) dist[i]=inf; dist[u]=0; priority_queue<node>q; q.push(node(u,dist[u])); while(!q.empty()) { node now=q.top();q.pop(); ll x=now.num; for(ll i=head[x];i!=-1;i=edge[i].next) { ll v=edge[i].to; if(dist[v]>dist[x]+edge[i].w) { dist[v]=dist[x]+edge[i].w; q.push(node(v,dist[v])); } } } } int main() { scanf("%lld%lld",&n,&m);memset(head,-1,sizeof(head));cnt=0; for(ll i=1;i<=m;i++) { scanf("%lld",&k); for(ll j=1;j<=k;j++) { scanf("%lld",&q); add(n+i,q,0); add(q,n+n+i,0); } } scanf("%lld",&m1); for(ll i=1;i<=m1;i++) { scanf("%lld%lld%lld",&x,&y,&w); add(x,y,w);add(y,x,w); } scanf("%lld",&m2); for(ll i=1;i<=m2;i++) { scanf("%lld%lld%lld",&x,&y,&w); add(n+n+x,n+y,w); add(n+n+y,n+x,w); } scanf("%lld%lld",&s,&t); dij(s); if(dist[t]==inf) printf("-1\n"); else printf("%lld\n",dist[t]); }