9.20题解

T1

考虑如果$k==0$,那么他就是一个裸的最长公共子序列,那么我们完全可以把$k$当作第$3$维,压进$dp$数组里,设$dp[i][j][k]$代表$A$串前$i$位和$B$串前$j$位匹配,修改了$k$次的最长公共子序列长度,多加一个转移方程就可以了,复杂度$O(n^3)$

 1 #include<iostream>
 2 #include<cstdio>
 3 #define maxn 305
 4 using namespace std;
 5 int n,k,ans,i,j,l;
 6 char a[maxn],b[maxn];
 7 int dp[maxn][maxn][maxn];
 8 int main()
 9 {
10     //freopen("1.in","r",stdin);
11     //freopen("W.out","w",stdout);
12     scanf("%d%d",&n,&k);
13     scanf("%s%s",a+1,b+1);
14     for(i=1;i<=n;++i)
15         for(j=1;j<=n;++j)
16             for(l=0;l<=k;++l)
17             {
18                 if(a[i]==b[j])  dp[i][j][l]=dp[i-1][j-1][l]+1;
19                 ans=max(ans,dp[i][j][l]);
20                 if(!l)  continue;
21                 dp[i][j][l]=max(dp[i][j][l],dp[i-1][j-1][l-1]+1);
22                 ans=max(ans,dp[i][j][l]);
23             }
24     printf("%d\n",ans);
25     return 0;
26 }
View Code

T2

考场上并没有深入思考这道题,事实上吧,看了题解之后发现他非常非常的简单,一共要四个不同的点,我们可以枚举中间的两个点,假设分别为$x$和$y$,那么这两个点对答案的贡献就是$du[x]{\times}du[y]$,$du$里不包括对方,这样的话有一个问题就是我们会出现三元环,一个很好的解决方法是$bieset$,这玩意一般情况下都非常好用,得到包含这两个点的三元环的方法是用$bitset$记录和这个点有之间连边的点,然后把$x$和$y$的$bitset$与起来,一的个数就是三元环的数量,复杂度$O(\frac{n^3}{32})$

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<bitset>
 5 #define maxn 2000
 6 #define ll long long
 7 using namespace std;
 8 int n,js;
 9 ll ans;
10 int du[maxn];
11 char s[maxn];
12 bitset <maxn> li[maxn];
13 bitset <maxn> ls;
14 int main()
15 {
16     scanf("%d",&n);
17     for(int i=1;i<=n;++i)
18     {
19         scanf("%s",s+1);
20         for(int j=1;j<=n;++j)
21             if(s[j]=='1')  {li[i][j]=1;  du[i]++;}
22     }
23     for(int i=1;i<=n;++i)
24         for(int j=i+1;j<=n;++j)
25             if(li[i][j])  {ans+=(du[i]-1)*(du[j]-1);  ls=li[i]&li[j];  ans-=ls.count();}
26     ans=ans*2;  printf("%lld\n",ans);
27     return 0;
28 }
View Code

T3

由于二进制的特性,我们考虑拆点,考虑对于每一个权值,向所有它的子集连边权为$0$的边,一个数和他的子集做与运算得到的一定是他的子集,也可以给这个数往上补一,让每个点向他的权值连边权为$1$的边,权值向点连边权为$0$的边,反过来也可以,一个$0$一个$1$就行,然后就跑最短路就可以了

还有一个点就是如果把所有的边都建出来,边过于多了,所以说我们不真正建出来,在跑$dj$的时候,记得有这些边就可以

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<vector>
 5 #include<queue>
 6 #define maxn 200200
 7 #define maxm 300300
 8 #define maxx 1300000
 9 #define maxM 700700
10 #define inf 1061109567
11 using namespace std;
12 struct node{
13     int di,pos;
14     bool operator < (const node &a)const
15     {
16         return a.di<di;
17     }
18 };
19 int n,m,u,v,js;
20 int head[maxx],to[maxM],xia[maxM],w[maxM];
21 int val[maxn],dis[maxx];
22 priority_queue <node> s;
23 int lowbit(int x)
24 {
25     return x&(-x);
26 }
27 void add(int x,int y,int z)
28 {
29     to[++js]=y;  xia[js]=head[x];  w[js]=z;  head[x]=js;
30 }
31 void dj(int x)
32 {
33     memset(dis,0x3f,sizeof(dis));
34     dis[x]=0;  s.push((node){dis[x],x});
35     while(s.size())
36     {
37         node ls=s.top();  s.pop();
38         if(ls.di!=dis[ls.pos])  continue;
39         for(int i=head[ls.pos];i;i=xia[i])
40         {
41             int lss=to[i];
42             if(dis[ls.pos]+w[i]<dis[lss])
43             {
44                 dis[lss]=dis[ls.pos]+w[i];
45                 s.push((node){dis[lss],lss});
46             }
47         }
48         if(ls.pos>n)
49         {
50             int l=ls.pos-n-1;
51             for(int j=l;j>0;j-=lowbit(j))
52             {
53                 int lsx=l-lowbit(j),lss=lsx+n+1;
54                 if(dis[ls.pos]<dis[lss])
55                 {
56                     dis[lss]=dis[ls.pos];
57                     s.push((node){dis[lss],lss});
58                 }
59             }
60         }
61     }
62 }
63 int main()
64 {
65     scanf("%d%d",&n,&m);
66     for(int i=1;i<=n;++i)  scanf("%d",&val[i]);
67     for(int i=1;i<=m;++i)  {scanf("%d%d",&u,&v);  add(u,v,1);}
68     for(int i=1;i<=n;++i)  {add(i,val[i]+n+1,1);  add(val[i]+n+1,i,0);}
69     dj(1);
70     for(int i=1;i<=n;++i)
71     {
72         if(dis[i]>=inf)  printf("-1\n");
73         else  printf("%d\n",dis[i]);
74     }
75     return 0;
76 }
View Code

 

posted @ 2019-10-15 17:51  hzoi_X&R  阅读(188)  评论(0编辑  收藏  举报