http://www.lydsy.com/JudgeOnline/problem.php?id=1097
首先还是我很sb。。。。想到了分层图想不到怎么串起来,,,以为用拓扑序搞转移,,后来感到不行。。。
QAQ
这种数据那么小,有明确的依赖性为嘛我想不到状压。。。(准确的说是没想到状压和分层图一起做。。。。
还有一个。。。。。。。为什么递推不行。。。(还是我写挫了。。。老wa。。)非得记忆化。。。。。。
(其实记忆化的话能省点不必要的状态吧。。。
。。。。
还有。。。和zyf一样,被卡在了。。!(s&(1<<(v-1)))。。。。。不去掉就tle。。也是喜闻乐见。。。
QAQ
(然后我spfa的vis标记打错了。。。。。。。调了好久。。QAQ
#include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue> #include <set> #include <map> using namespace std; typedef long long ll; #define rep(i, n) for(int i=0; i<(n); ++i) #define for1(i,a,n) for(int i=(a);i<=(n);++i) #define for2(i,a,n) for(int i=(a);i<(n);++i) #define for3(i,a,n) for(int i=(a);i>=(n);--i) #define for4(i,a,n) for(int i=(a);i>(n);--i) #define CC(i,a) memset(i,a,sizeof(i)) #define read(a) a=getint() #define print(a) printf("%d", a) #define dbg(x) cout << (#x) << " = " << (x) << endl #define error(x) (!(x)?puts("error"):0) #define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next) #define grdm(g, x, i) for(int i=g.ihead[x]; i; i=g.e[i].next) inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } const int N=50005, oo=0x3f3f3f3f; int d[22][N], vis[N], q[N], ihead[N], cnt, n, m, k; struct dat { int next, to, w; }e[N*10*2]; void add1(int u, int v, int w) { e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[cnt].w=w; } void add(int u, int v, int w) { add1(u, v, w); add1(v, u, w); } void spfa(int s, int *f) { memset(vis, 0, sizeof(int)*(n)); memset(f, 0x3f, sizeof(int)*(n)); int front=0, tail=0; f[s]=0; q[tail++]=s; vis[s]=1; while(front!=tail) { int u=q[front++], v; if(front==N) front=0; vis[u]=0; rdm(u, i) if(f[v=e[i].to]>f[u]+e[i].w) { f[v]=f[u]+e[i].w; if(!vis[v]) { vis[v]=1; if(f[q[front]]>f[v]) { --front; if(front<0) front+=N; q[front]=v; } else { q[tail++]=v; if(tail==N) tail=0; } } } } } int ans[21][1<<(20)], b[22], all; int dfs(int u, int s) { if(ans[u][s]>=0) return ans[u][s]; if(s==all) return d[u][n-1]; int &a=ans[u][s]; a=oo; for1(v, 1, k) if((b[v]&s)==b[v]) a=min(a, d[u][v]+dfs(v, s|(1<<(v-1)))); return a; } int main() { read(n); read(m); read(k); for1(i, 1, m) { int u=getint(), v=getint(), w=getint(); add(u-1, v-1, w); } for1(i, 0, k) spfa(i, d[i]); read(m); for1(i, 1, m) { int u=getint(), v=getint(); b[v-1]|=(1<<(u-2)); } all=(1<<k)-1; CC(ans, -1); printf("%d ", dfs(0, 0)); return 0; }
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,总长度为19。注意FGD为了从城市2到城市4可以路过城市3,但不在城市3停留。这样就不违反FGD的要求了。并且由于FGD想要走最短的路径,因此这个方案正是FGD需要的。
Input
第一行包含3个整数N(2<=N<=20000),M(1<=M<=200000),K(0<=K<=20),意义如上所述。以下M行,每行包含3个整数X,Y,Z,(1<=X
Output
只包含一行,包含一个整数,表示最短的旅行距离。
Sample Input
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
HINT
上面对应于题目中给出的例子。