【牛客CSP-S提高組賽前集訓營5】B 十二橋問題(最短路+狀壓DP)

文章目錄

題目

十二橋問題

分析

k12k\leq12,果斷考慮狀壓。

將所有必須走的邊的端點u,vu,v視爲關鍵點,爲每個關鍵點跑Dijkstra,然後狀壓DP。

dp[S][i][0]dp[S][i][0]表示走完集合爲SS的邊,最後停在第ii條邊的uu點的最小代價;
dp[S][i][1]dp[S][i][1]表示走完集合爲SS的邊,最後停在第ii條邊的vv點的最小代價。

每次轉移考慮從上一條邊的u,vu,v走最短路走過來,再強制走邊uvu\leftrightarrow v

有個問題是要求從11開始,又回到11,其實很簡單:把邊(u=1,v=1,w=0)(u=1,v=1,w=0)作爲關鍵邊再跑狀壓DP,並且狀壓的集合裏要求必須有這條邊,就可以了。

代碼

可能是我寫得太醜了被卡常,用了超級讀入掛+vector+register才過,少一樣都不行。
我死了

#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
 
#ifndef LOACL
#define getchar() (*(IOB.in.p++))
#define putchar(c) (*(IOB.out.p++) = (c))
#define io_eof() (IOB.in.p >= IOB.in.pend)
struct IOBUF {
    struct {
        char buff[1 << 27], *p, *pend;
    } in;
    struct {
        char buff[1 << 27], *p;
    } out;
    IOBUF() {
        in.p = in.buff, out.p = out.buff;
        in.pend = in.buff + fread(in.buff, 1, 1 << 27, stdin);
    }
    ~IOBUF() {
        fwrite(out.buff, 1, out.p - out.buff, stdout);
    }
} IOB;
#endif
template <typename IO>
inline void write(IO val) {
    if(val == 0) {
        putchar('0');
        return;
    }
    if(val < 0) {
        putchar('-');
        val = -val;
    }
    static char buf[30];
    char *p = buf;
    while(val) {
        *(p++) = val % 10 + '0';
        val /= 10;
    }
    while(p > buf) putchar(*(--p));
}
inline void writestr(const char *s) {
    while(*s != 0) putchar(*(s++));
}
template <typename IO>
inline void writeln(IO val) {write(val), putchar('\n');}
template <typename IO>
inline void writesp(IO val) {write(val), putchar(' ');}
inline int readstr(char *s) {
    char *begin = s, c = getchar();
    while(c < 33 || c > 127)
        c = getchar();
    while(c >= 33 && c <= 127)
        *(s++) = c, c = getchar();
    *s = 0;
    return s - begin;
}
template <typename IO>
inline IO read() {
    IO ret = 0;
    register bool w = 0;
    register char c = getchar();
    while(c > '9' || c < '0') {
        if(c == '-') w = 1;
        c = getchar();
    }
    while(c >= '0' && c <='9') {
        ret = (ret << 3) + (ret << 1) + (c ^ 48);
        c = getchar();
    }
    return w ? -ret : ret;
}
 
#define MAXK (12+1)
#define MAXN 50000
#define MAXM 200000
#define LL long long
#define INF 1000000000000000000ll
#define PII pair<int,int>
#define PLI pair<long long,int>
 
int N,M,K;
int KeyNode[MAXN+5];
vector<PII> G[MAXN+5];
struct Edge{
    int u,v,w;
}E[MAXM+5];
 
struct DistNode{
    int u;LL d;
    DistNode(){}
    DistNode(int x,int y):
        u(x),d(y){}
    bool operator < (const DistNode other) const{
        return d>other.d;
    }
};
LL Dist[2*MAXK+5][MAXN+5];
void Dijkstra(int S,LL *Dist,PII Ban){
    priority_queue<DistNode> Q;
    fill(Dist+1,Dist+N+1,INF);
    Q.push(DistNode(S,Dist[S]=0));
    while(!Q.empty()){
        int u=Q.top().u;LL d=Q.top().d;Q.pop();
        if(d>Dist[u]) continue;
        for(register int i=0;i<int(G[u].size());i++){
            int v=G[u][i].first,w=G[u][i].second;
            if((u==Ban.first&&v==Ban.second)||
               (u==Ban.second&&v==Ban.first))
                continue;
            if(Dist[v]>Dist[u]+w){
                Dist[v]=Dist[u]+w;
                Q.push(DistNode(v,Dist[v]));
            }
        }
    }
}
 
#define MAXS (1<<MAXK)
LL dp[MAXS+5][MAXK+5][2];
 
int main(){
    int cnt=0;
    N=read<int>(),M=read<int>(),K=read<int>();
    K++;
    E[1].u=E[1].v=1,E[1].w=0;
    for(register int i=1;i<=M;i++){
        int u=read<int>(),v=read<int>(),w=read<int>();
        G[u].push_back(make_pair(v,w));
        G[v].push_back(make_pair(u,w));
        E[i+1].u=u,E[i+1].v=v,E[i+1].w=w;
    }
    for(register int i=1;i<=K;i++){
        int u=E[i].u,v=E[i].v;
        if(!KeyNode[u])
            Dijkstra(u,Dist[KeyNode[u]=++cnt],make_pair(u,v));
        if(!KeyNode[v])
            Dijkstra(v,Dist[KeyNode[v]=++cnt],make_pair(u,v));
    }
    register int All=(1<<K)-1;
    dp[1][1][0]=dp[1][1][1]=0;
    for(register int S=2;S<=All;S++)
        dp[S][1][0]=dp[S][1][1]=INF;
    for(register int S=3;S<=All;S+=2){
        for(register int i=2;i<=K;i++){
            if(!(S&(1<<(i-1))))
                continue;
            int T=S^(1<<(i-1));
            int iu=E[i].u,iv=E[i].v,iw=E[i].w;
            dp[S][i][0]=dp[S][i][1]=INF;
            for(register int j=1;j<=K;j++){
                if(i==j||(!(S&(1<<(j-1)))))
                    continue;
                int ju=E[j].u,jv=E[j].v;
                int juk=KeyNode[ju],jvk=KeyNode[jv];
                dp[S][i][0]=min(dp[S][i][0],min(dp[T][j][0]+Dist[juk][iv]+iw,dp[T][j][1]+Dist[jvk][iv]+iw));
                dp[S][i][1]=min(dp[S][i][1],min(dp[T][j][0]+Dist[juk][iu]+iw,dp[T][j][1]+Dist[jvk][iu]+iw));
            }
        }
    }
    LL Ans=INF;
    for(register int i=2;i<=K;i++){
        int iuk=KeyNode[E[i].u],ivk=KeyNode[E[i].v];
        Ans=min(Ans,min(dp[All][i][0]+Dist[iuk][1],dp[All][i][1]+Dist[ivk][1]));
    }
    printf("%lld",Ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章