HDU - 5521 巧妙地最短路
阿新 • • 發佈:2018-11-05
題意:n個點,m塊,塊的意思就是說,在塊中的點任意兩點的距離都是t,問分別從1點和n點走到某個點,這個點的花費就是二者較大的,問這n個點花費最小是多少,並按字典序列印序號
思路:這題頭疼的就是不知道怎麼建圖,暴力建圖會超記憶體,有一個巧妙的方法是
將這個塊中的點全部連到一個點上,每條邊花費t/2,這樣任意兩點仍然是t的花費。
這樣最多1e6條邊
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; typedef long long ll; const ll INF=99999999999999999; struct node{ int v; ll w; }; vector<node> G[N]; ll dis1[N], dis2[N], dis[N]; int n, m; int ans[N], tot; bitset<N> inq; void spfa(int s, ll dd[]){ for(int i=1; i<=n+m; i++) dd[i]=INF; inq.reset(); dd[s]=0; queue<int> q; q.push(s); inq[s]=1; while(!q.empty()){ int u=q.front(); q.pop(); inq[u]=0; for(int i=0; i<G[u].size(); i++){ int v=G[u][i].v; ll w=G[u][i].w; if(dd[v]>dd[u]+w){ dd[v]=dd[u]+w; if(!inq[v]){ inq[v]=1; q.push(v); } } } } } void init(){ for(int i=1; i<=n+m; i++){ G[i].clear(); } } int main(){ int T, cas=0; scanf("%d", &T); while(T--){ scanf("%d%d", &n, &m); init(); for(int i=1; i<=m; i++){ int ti, si; scanf("%d%d", &ti, &si); for(int j=1; j<=si; j++){ int p; scanf("%d", &p); G[n+i].push_back((node){p, ti}); G[p].push_back((node){n+i, ti}); } } spfa(1, dis1); spfa(n, dis2); ll mn=INF; for(int i=1; i<=n; i++){ dis[i]=max(dis1[i], dis2[i]); mn=min(dis[i], mn); } printf("Case #%d: ", ++cas); if(mn==INF){ printf("Evil John\n"); continue; } printf("%lld\n", mn/2); tot=0; for(int i=1; i<=n; i++){ if(mn==dis[i]) ans[++tot]=i; // printf("%lld ", dis[i]); } // puts(""); for(int i=1; i<=tot; i++){ printf("%d", ans[i]); if(i==tot) putchar('\n'); else putchar(' '); } } return 0; }