Description
FGD想从成都去上海旅游。在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣
的事情。经过这些城市的顺序不是完全随意的,比如说FGD不希望在刚吃过一顿大餐之后立刻去下一个城市登山,
而是希望去另外什么地方喝下午茶。幸运的是,FGD的旅程不是既定的,他可以在某些旅行方案之间进行选择。由于
FGD非常讨厌乘车的颠簸,他希望在满足他的要求的情况下,旅行的距离尽量短,这样他就有足够的精力来欣赏风
景或者是泡MM了_.整个城市交通网络包含N个城市以及城市与城市之间的双向道路M条。城市自1至N依次编号,道
路亦然。没有从某个城市直接到它自己的道路,两个城市之间最多只有一条道路直接相连,但可以有多条连接两个
城市的路径。任意两条道路如果相遇,则相遇点也必然是这N个城市之一,在中途,由于修建了立交桥和下穿隧道
,道路是不会相交的。每条道路都有一个固定长度。在中途,FGD想要经过K(K<=N-2)个城市。成都编号为1,上海
编号为N,而FGD想要经过的N个城市编号依次为2,3,…,K+1.举例来说,假设交通网络如下图。FGD想要经过城市2,3,
4,5,并且在2停留的时候在3之前,而在4,5停留的时候在3之后。那么最短的旅行方案是1-2-4-3-4-5-8,总长度为1
9。注意FGD为了从城市2到城市4可以路过城市3,但不在城市3停留。这样就不违反FGD的要求了。并且由于FGD想要
走最短的路径,因此这个方案正是FGD需要的。
Input
第一行包含3个整数N(2<=N<=20000),M(1<=M<=200000),K(0<=K<=20),意义如上所述。
Output
只包含一行,包含一个整数,表示最短的旅行距离。
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
题解
发现K很小
可以搞事情
设 表示最后一个停留的位置为i,已经停留过的点的状态为k
dij出每个点的最短路
大力转移就行了.
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#define LL long long
#define mp(x,y) make_pair(x,y)
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void write(int x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
inline void print(int x){write(x);printf(" ");}
struct qq{int x,y,next;}e[8100];int len2,last2[410];
void ins2(int x,int y){len2++;e[len2].x=x;e[len2].y=y;e[len2].next=last2[x];last2[x]=len2;}
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
struct node{int x,y,c,next;}a[411000];int len,last[21000];
void ins(int x,int y,int c){len++;a[len].x=x;a[len].y=y;a[len].c=c;a[len].next=last[x];last[x]=len;}
int d[22][21000];bool v[21000];
void dij(int st)
{
memset(v,false,sizeof(v));memset(d[st],63,sizeof(d[st]));
d[st][st]=0;q.push(mp(0,st));
while(!q.empty())
{
int x=q.top().second;q.pop();
if(v[x])continue;v[x]=1;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(d[st][y]>d[st][x]+a[k].c)
{
d[st][y]=d[st][x]+a[k].c;
q.push(mp(d[st][y],y));
}
}
}
}
int n,m,K,T;
int nxt[25][25],bin[30];
int ok[(1<<20)+5],ok1[22][1048576];
int f[22][1048576];
int main()
{
bin[2]=1;for(int i=3;i<=25;i++)bin[i]=bin[i-1]<<1;
n=read();m=read();K=read();
for(int i=1;i<=m;i++)
{
int x=read(),y=read(),c=read();
ins(x,y,c);ins(y,x,c);
}
if(!K)
{
dij(1);
printf("%d\n",d[1][n]);return 0;
}
for(int i=1;i<=K+1;i++)
dij(i);
T=read();
for(int i=1;i<=T;i++)
{
int x=read(),y=read();
ins2(y,x);nxt[x][y]=1;
}
ok[0]=1;
for(int i=0;i<bin[K+2];i++)
if(ok[i])
for(int j=2;j<=K+1;j++)if(!(i&bin[j]))
{
bool tf=true;
for(int k=last2[j];k;k=e[k].next)if(!(i&bin[e[k].y])){tf=false;break;}
ok[i|bin[j]]=tf;ok1[j][i]=tf;
}
memset(f,63,sizeof(f));
for(int i=2;i<=K+1;i++)
if(ok[bin[i]])f[i][bin[i]]=d[1][i];
for(int i=1;i<bin[K+2];i++)
if(ok[i])
for(int j=2;j<=K+1;j++)if(!(i&bin[j])&&ok1[j][i])
{
for(int k=2;k<=K+1;k++)if(i&bin[k])
f[j][i|bin[j]]=min(f[j][i|bin[j]],f[k][i]+d[k][j]);
}
int ans=999999999;
for(int i=2;i<=K+1;i++)
ans=min(ans,f[i][bin[K+2]-1]+d[i][n]);
printf("%d\n",ans);
return 0;
}