1. 程式人生 > >HDU - 5521 巧妙地最短路

HDU - 5521 巧妙地最短路

題意: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;
}