斯坦纳树

大意: 给定一张图 求图上一个点集的最小生成树。

 

考虑状态压缩 状态 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\n",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("\n");
149     }
150     return 0;
151 }
View Code

 

 

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\n",ans);
119     return 0;
120 }
View Code

 

格式化插件是个好东西 biiiiiiiiiiiiiiiiiiiiiiiiii

posted @ 2017-01-06 10:47  蛤鸡  阅读(328)  评论(0编辑  收藏  举报