[POI2007] Tourist attractions atr

Description
FGD wants to travel from Chengdu to Shanghai. During the trip he wants to pass through some cities and enjoy the scenery there, eat delicious snacks or do other interesting things. The order of passing through these cities is not completely random. For example, FGD does not want to go to the next city to climb a mountain immediately after having just eaten a big meal, but wants to go somewhere else for afternoon tea. Fortunately, FGD's journey is not predetermined and he can choose between certain travel options. Since FGD hates the bumpy ride, he hopes to travel as short a distance as possible while meeting his requirements, so that he has enough energy to enjoy the scenery or take a MM ^_^. The entire city transportation network includes N cities and M two-way roads between cities. Cities are numbered from 1 to N, as are roads. There is no direct road from a city to itself, at most one road is directly connected between two cities, but there can be multiple paths connecting two cities. If any two roads meet, the meeting point must be one of the N cities. In the middle, the roads will not intersect due to the construction of overpasses and tunnels. Each road has a fixed length. On the way, FGD wants to pass through K(K<=N-2) cities. Chengdu is numbered 1, Shanghai is numbered N, and the N cities that FGD wants to pass through are numbered 2,3,…,K+1. For example, suppose the transportation network is as shown below. FGD wants to go through cities 2,3,4,5 and be before 3 when 2 stops and after 3 when 4,5 stop. Then the shortest travel scenario is 1-2-4-3-4-5-8 with a total length of 19. Note that FGD can pass through city 3 in order to get from city 2 to city 4, but not stop at city 3. This will not violate the requirements of FGD. And since FGD wants to take the shortest path, this scheme is exactly what FGD needs.

The first line of Input
contains 3 integers N(2<=N<=20000), M(1<=M<=200000), K(0<=K<=20), the meanings are as described above.
After that, there are q restrictions, each time a pair of \(x_i,y_i\) is given , which means that \(x_i\) has to rest before \(y_i\)

Output
contains only one line containing an integer representing the shortest travel distance.

Sample Input
8 15 4
1 2 3
1 3 4
1 4 4
1 6 2
1 7 3
2 3 6
2 4 2
2 5 2
3 4 3
3 6 3
3 8 6
4 5 2
4 8 6
5 7 4
5 8 6
3
2 3
3 4
3 5

Sample Output
19

HINT

The picture above is the example given in the title

I don't want to say anything about this question, and the input description of the question is not clear... Seeing k<=20, isn't this directly pressing up?
All the distances between the points 1~k+1 are processed, and then for each point Write down a limit and you can use it to press DP happily.
In the case of K=0, it is pitted

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
    int x=0,f=1;char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<3)+(x<<1)+ch-'0';
    return x*f;
}
inline void write(int x){
    if (x>=10)  write(x/10);
    putchar(x%10+'0');
}
const int N=2e4,M=2e5,K=20;
int pre[(M<<1)+10],now[N+10],child[(M<<1)+10],val[(M<<1)+10];
int h[N+10],deep[N+10];
bool vis[N+10];
int dis[K+5][K+5],f[21][1<<K],v[K+5];
int n,m,k,tot,Ans=inf;
void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}
void SPFA(int x){//预处理,dijkstra会快一些,但是我懒
    memset(vis,0,sizeof(vis));
    memset(deep,63,sizeof(deep));
    int head=0,tail=1;
    h[1]=x,vis[x]=1,deep[x]=0;
    while (head!=tail){
        if (++head>N)   head=1;
        int Now=h[head];
        for (int p=now[Now],son=child[p];p;p=pre[p],son=child[p]){
            if (deep[son]>deep[Now]+val[p]){
                deep[son]=deep[Now]+val[p];
                if (!vis[son]){
                    if (++tail>N)   tail=1;
                    vis[h[tail]=son]=1;
                }
            }
        }
        vis[Now]=0;
    }
    for (int i=1;i<=k+1;i++)    dis[x][i]=deep[i];
    dis[x][0]=deep[n];
}
void dp(){
    memset(f,63,sizeof(f));
    for (int i=1;i<=k;i++)  if (!v[i])  f[i][1<<(i-1)]=dis[1][i+1];
    for (int sta=1;sta<1<<k;sta++){
        for (int i=1;i<=k;i++){
            if ((f[i][sta]==inf)||(!(sta&(1<<(i-1)))))  continue;
            for (int j=1;j<=k;j++){
                if (((v[j]&sta)==v[j])&&(!(sta&(1<<(j-1))))){
                    f[j][sta|(1<<(j-1))]=min(f[j][sta|(1<<(j-1))],f[i][sta]+dis[i+1][j+1]);
                }
            }
        }
    }
}
int main(){
    n=read(),m=read(),k=read();
    for (int i=1;i<=m;i++){
        int x=read(),y=read(),z=read();
        join(x,y,z),join(y,x,z);
    }
    if (!k){SPFA(1);printf("%d\n",deep[n]);return 0;}//特判
    for (int i=1;i<=k+1;i++)    SPFA(i);
    int q=read();
    for (int i=1;i<=q;i++){//由于他要经过的点是2~k+1,所以处理起来会有点小恶心
        int x=read(),y=read();
        v[y-1]|=1<<(x-2);
    }
    dp();
    for (int i=1;i<=k;i++)  Ans=min(Ans,f[i][(1<<k)-1]+dis[i+1][0]);
    printf("%d\n",Ans);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324604101&siteId=291194637