标签:
题目求从某点出发回到该点经过所有边至少一次的最短行程。
而这一题的问题就可以转化给这个无向图加最短的边使其所有点的度位偶数(为什么不说欧拉回路,因为题目没说图一定连通。。
这道题在LightOJ分类是DP。。我想大概就是15个点二进制压缩的状压DP。也就是把各点度为偶数奇数分别看作二进制各位0和1,然后每次可以通过在任意两个奇度或偶度点加一条边来转移。。
不过显然这是不行的,这样的状态不满足DP的无后效性,状态是点转移是边那就可以是个有向有环图——有向有环图——于是我就想到最短路,显然可以用最短路做,不过时间复杂度不好说。。具体来说:
如此构图,跑个SPFA,然后就AC了。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 #define INF (1<<30) 6 int n,map[15][15]; 7 int d[1<<15]; 8 bool vis[1<<15]; 9 int SPFA(int vs){ 10 for(int i=0; i<(1<<15); ++i){ 11 d[i]=INF; vis[i]=0; 12 } 13 d[vs]=0; vis[vs]=1; 14 queue<int> que; 15 que.push(vs); 16 while(!que.empty()){ 17 int u=que.front(); que.pop(); 18 for(int i=0; i<n; ++i){ 19 for(int j=i+1; j<n; ++j){ 20 if(map[i][j]==-1) continue; 21 int v=u; v^=(1<<i); v^=(1<<j); 22 if(d[v]>d[u]+map[i][j]){ 23 d[v]=d[u]+map[i][j]; 24 if(!vis[v]){ 25 vis[v]=1; 26 que.push(v); 27 } 28 } 29 } 30 } 31 vis[u]=0; 32 } 33 return d[0]; 34 } 35 int main(){ 36 int t,m,a,b,c; 37 scanf("%d",&t); 38 for(int cse=1; cse<=t; ++cse){ 39 scanf("%d%d",&n,&m); 40 memset(map,-1,sizeof(map)); 41 int deg[15]={0},res=0; 42 while(m--){ 43 scanf("%d%d%d",&a,&b,&c); 44 --a; --b; 45 ++deg[a]; ++deg[b]; res+=c; 46 if(map[a][b]==-1 || map[a][b]>c) map[a][b]=map[b][a]=c; 47 } 48 int vs=0; 49 for(int i=0; i<n; ++i){ 50 if(deg[i]&1) vs|=(1<<i); 51 } 52 res+=SPFA(vs); 53 printf("Case %d: %d\n",cse,res); 54 } 55 return 0; 56 }
LightOJ1086 Jogging Trails(欧拉回路+中国邮递员问题+SPFA)
标签:
原文地址:http://www.cnblogs.com/WABoss/p/5140531.html