大意: 给定一张图 求图上一个点集的最小生成树。
考虑状态压缩 状态 dp[i][j] 为 当前走在 点i 状态为j 每一位表示 是否已在生成树中
于是 spfa 过程可以更新 -> 在每一个节点上均可考虑 移动 或者 与在该点上的其他状态进行合并
根据题目的描述 可以 微调 dp 过程 为什么我的常数大的可怕 又或者 是写得太残 或是 这题其实可以更妙 总而言之 还是太naive
bzoj 2595
1 #include <bits/stdc++.h> 2 #define p(i,j) (i-1)*m+j 3 #define inf 0x3fffffff 4 using namespace std; 5 6 inline int read() 7 { 8 int x=0,f=1; 9 char ch=getchar(); 10 while(ch<'0'||ch>'9') 11 { 12 if(ch=='-')f=-1; 13 ch=getchar(); 14 } 15 while(ch>='0'&&ch<='9') 16 { 17 x=x*10+ch-'0'; 18 ch=getchar(); 19 } 20 return x*f; 21 } 22 struct edge 23 { 24 int u,v,next; 25 } vs[300000]; 26 struct state 27 { 28 int at,mask; 29 }; 30 int n,m,st[2010],ee,fang[4][2]= {{1,0},{-1,0},{0,1},{0,-1}}; 31 int pl[12],tot,vis[2100][4100],ans=0; 32 char mmp[12][12]; 33 int dis[2100][4100],pre[2110][4100][2][2],val[2100]; 34 inline void addedge(int u,int v) 35 { 36 vs[++ee].v=v; 37 vs[ee].u=u; 38 vs[ee].next=st[u]; 39 st[u]=ee; 40 } 41 void getpos(int x,char c) 42 { 43 int xx=x/m+1,y=(x%m==0)? m:x%m; 44 if(x%m==0)xx--; 45 mmp[xx][y]=c; 46 } 47 void gethash(state&a,int b) 48 { 49 for(int i=1; i<=tot; i++) 50 if(pl[i]==b)a.mask|=(1<<i-1); 51 } 52 void spfa() 53 { 54 queue <state> q; 55 state tmp; 56 for(int i=1; i<=n*m; i++) 57 { 58 tmp.at=i; 59 tmp.mask=0; 60 gethash(tmp,i); 61 q.push(tmp); 62 dis[tmp.at][tmp.mask]=val[tmp.at]; 63 vis[tmp.at][tmp.mask]=1; 64 } 65 while(!q.empty()) 66 { 67 state lx=q.front(); 68 q.pop(); 69 if(lx.mask==(1<<tot)-1) continue; 70 //move 71 for(int i=st[lx.at]; i; i=vs[i].next) 72 { 73 tmp.at=vs[i].v; 74 tmp.mask=lx.mask; 75 gethash(tmp,vs[i].v); 76 if(dis[tmp.at][tmp.mask]>dis[lx.at][lx.mask]+val[tmp.at]) 77 { 78 dis[tmp.at][tmp.mask]=dis[lx.at][lx.mask]+val[tmp.at]; 79 pre[tmp.at][tmp.mask][0][0]=lx.at; 80 pre[tmp.at][tmp.mask][1][0]=lx.mask; 81 pre[tmp.at][tmp.mask][0][1]=0; 82 pre[tmp.at][tmp.mask][1][1]=0; 83 if(!vis[tmp.at][tmp.mask]) q.push(tmp),vis[tmp.at][tmp.mask]=1; 84 } 85 } 86 //merge 87 for(int i=1; i<(1<<tot); i++) 88 { 89 tmp.at=lx.at; 90 tmp.mask=lx.mask; 91 tmp.mask|=i; 92 if(dis[tmp.at][tmp.mask]>dis[lx.at][lx.mask]+dis[lx.at][i]-val[lx.at]) 93 { 94 dis[tmp.at][tmp.mask]=dis[lx.at][lx.mask]+dis[lx.at][i]-val[lx.at]; 95 pre[tmp.at][tmp.mask][0][0]=lx.at; 96 pre[tmp.at][tmp.mask][1][0]=lx.mask; 97 pre[tmp.at][tmp.mask][0][1]=lx.at; 98 pre[tmp.at][tmp.mask][1][1]=i; 99 if(!vis[tmp.at][tmp.mask]) q.push(tmp),vis[tmp.at][tmp.mask]=1; 100 } 101 } 102 vis[lx.at][lx.mask]=0; 103 } 104 } 105 void fillwith(int x1,int x2) 106 { 107 if(!x1&&!x2) return ; 108 // printf("%d ",dis[x1][x2]); 109 if(val[x1]) getpos(x1,'o'); 110 else getpos(x1,'x'); 111 fillwith(pre[x1][x2][0][0],pre[x1][x2][1][0]); 112 fillwith(pre[x1][x2][0][1],pre[x1][x2][1][1]); 113 } 114 void makeways() 115 { 116 int g=0; 117 for(int i=1; i<=n; i++) 118 for(int j=1; j<=n; j++) 119 if(dis[p(i,j)][(1<<tot)-1]<dis[g][(1<<tot)-1]) 120 g=p(i,j); 121 cout<<dis[g][(1<<tot)-1]<<endl; 122 fillwith(g,(1<<tot)-1); 123 } 124 int main() 125 { 126 for(int i=0; i<=100; i++) for(int k=0; k<=1024; k++) dis[i][k]=inf; 127 n=read(); 128 m=read(); 129 for(int i=1; i<=n; i++) 130 for(int j=1; j<=m; j++) 131 { 132 val[p(i,j)]=read(); 133 if(!val[p(i,j)]) pl[++tot]=p(i,j); 134 for(int k=0; k<4; k++) 135 { 136 int mx=i+fang[k][0],my=j+fang[k][1]; 137 if(mx<1||my<1||mx>n||my>m) continue; 138 addedge(p(i,j),p(mx,my)); 139 } 140 } 141 for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) mmp[i][j]='_'; 142 spfa(); 143 makeways(); 144 for(int i=1; i<=n; i++) 145 { 146 for(int j=1; j<=m; j++) 147 printf("%c",mmp[i][j]); 148 printf(" "); 149 } 150 return 0; 151 }
xjoi ????
1 #include <bits/stdc++.h> 2 #define inf 0x3fffffff 3 using namespace std; 4 5 int n,m,mps[40][40],c1,c2,k,ans; 6 char s[40][100],tmp1[40],tmp2[40]; 7 int ms[40][8],vis[40][1000],dis[40][1000]; 8 struct node 9 { 10 int p,z; 11 }; 12 queue <node> q; 13 void topl(node &a,int pl) 14 { 15 for(int i=1; i<=ms[pl][0]; i++) 16 a.z|=(1<<ms[pl][i]); 17 } 18 bool getfree(node a) 19 { 20 for(int i=0; i<4; i++) 21 { 22 int g=(a.z>>i*2)&3; 23 if(g!=0&&g!=3) return 0; 24 } 25 return 1; 26 } 27 void spfa() 28 { 29 node tmp; 30 memset(dis,-1,sizeof(dis)); 31 for(int i=1; i<=n; i++) 32 { 33 tmp.p=i; 34 tmp.z=0; 35 topl(tmp,i); 36 q.push(tmp); 37 vis[i][tmp.z]=1; 38 dis[i][tmp.z]=0; 39 } 40 while(!q.empty()) 41 { 42 node lx=q.front(); 43 q.pop(); 44 if(lx.z==(1<<8)-1) 45 ans=min(ans,dis[lx.p][lx.z]); 46 bool ok=getfree(lx); 47 //stay 48 for(int i=0; i<(1<<8); i++) 49 { 50 if(dis[lx.p][i]==-1) continue; 51 if(dis[lx.p][i|lx.z]==-1||dis[lx.p][i|lx.z]>dis[lx.p][i]+dis[lx.p][lx.z]) 52 { 53 dis[lx.p][i|lx.z]=dis[lx.p][i]+dis[lx.p][lx.z]; 54 if(!vis[lx.p][i|lx.z]) 55 { 56 tmp.p=lx.p; 57 tmp.z=i|lx.z; 58 q.push(tmp); 59 vis[tmp.p][tmp.z]=1; 60 } 61 } 62 } 63 //move 64 for(int i=1; i<=n; i++) 65 { 66 if(mps[lx.p][i]==inf) continue; 67 int w=ok? 0:mps[lx.p][i]; 68 tmp=lx; 69 tmp.p=i; 70 topl(tmp,i); 71 if(dis[tmp.p][tmp.z]>dis[lx.p][lx.z]+w||dis[tmp.p][tmp.z]==-1) 72 { 73 dis[tmp.p][tmp.z]=dis[lx.p][lx.z]+w; 74 if(!vis[tmp.p][tmp.z]) 75 { 76 q.push(tmp); 77 vis[tmp.p][tmp.z]=1; 78 } 79 } 80 } 81 82 } 83 } 84 bool check(char a[],char b[]) 85 { 86 int al=strlen(a),bl=strlen(b); 87 if(al!=bl) return 0; 88 for(int i=0; i<al; i++) 89 if(a[i]!=b[i]) return 0; 90 return 1; 91 } 92 int find(char ch[]) 93 { 94 for(int i=1; i<=n; i++) 95 if(check(ch,s[i])) return i; 96 } 97 int main() 98 { 99 scanf("%d%d",&n,&m); 100 ans=inf; 101 for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) mps[i][j]=inf; 102 for(int i=1; i<=n; i++) 103 scanf("%s",s[i]); 104 for(int i=1; i<=m; i++) 105 { 106 scanf("%s%s%d",tmp1,tmp2,&k); 107 c1=find(tmp1); 108 c2=find(tmp2); 109 mps[c1][c2]=mps[c2][c1]=min(mps[c1][c2],k); 110 } 111 for(int i=1; i<=8; i++) 112 { 113 scanf("%s",tmp1); 114 int c1=find(tmp1); 115 ms[c1][++ms[c1][0]]=i-1; 116 } 117 spfa(); 118 printf("%d ",ans); 119 return 0; 120 }
格式化插件是个好东西 biiiiiiiiiiiiiiiiiiiiiiiiii