停课集训 11.28

  网络流刷题日

 

  1.洛谷1343地震逃生

  先复习了一波dinic,随便写了个程序

  

  很裸的题目啊,直接建图maxflow再除一除。

  

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #define ll long long
 7 #define N 205
 8 using namespace std;
 9 int n,m,x,tot,hd[N],cur[N],vis[N],d[N];
10 struct edge{int v,next,flow,cap;}e[N*20];
11 
12 void adde(int u,int v,int c){
13     e[tot].v=v;
14     e[tot].cap=c;
15     e[tot].next=hd[u];
16     hd[u]=tot++;
17 }
18 
19 bool bfs(){
20     queue<int>q;
21     memset(vis,0,sizeof(vis));
22     q.push(1);d[1]=0;vis[1]=1;
23     while(!q.empty()){
24         int u=q.front();q.pop();
25         for(int i=hd[u];~i;i=e[i].next){
26             int v=e[i].v;
27             if(e[i].cap-e[i].flow<=0||vis[v])continue;
28             d[v]=d[u]+1;vis[v]=1;
29             q.push(v);
30         }
31     }
32     return vis[n];
33 }
34 int dfs(int u,int a){
35     if(!a||u==n)return a;
36     int flow=0,f;
37     for(int &i=cur[u];~i;i=e[i].next){
38         int v=e[i].v;
39         if(d[u]+1==d[v]&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
40             e[i].flow+=f;
41             e[i^1].flow-=f;
42             flow+=f;a-=f;
43             if(!a)break;
44         }
45     }
46     return flow;
47 }
48 
49 int main(){
50     //freopen(".in","r",stdin);
51     //freopen(".out","w",stdout);
52     memset(hd,-1,sizeof(hd));
53     scanf("%d%d%d",&n,&m,&x);
54     for(int i=1;i<=m;i++){
55         int a,b,c;
56         scanf("%d%d%d",&a,&b,&c);
57         adde(a,b,c);adde(b,a,0);
58     }
59     int a1=0,a2=0;
60     while(bfs()){
61         for(int i=1;i<=n;i++)cur[i]=hd[i];
62         a1+=dfs(1,2147483647);
63     }
64     if(!a1){
65         printf("Orz Ni Jinan Saint Cow!");
66         return 0;
67     }
68     if(x%a1)a2=x/a1+1;
69     else a2=x/a1;
70     printf("%d %d",a1,a2);
71     return 0;
72 }
View Code

  

  2. 洛谷1251餐巾纸问题

   然后学习了一下zkw费用流,大概就是用dinic跑费用流,,快的飞起

  

  建图还很麻烦。把每天拆成ai,bi两点,ai表示用过的,bi没用过。建立超级源汇S,T。

  (1)S向ai连容量r[i],费用0的边,S向bi连容量r[i],费用p的边

  (2)bi向T连容量r[i],费用0的边

  (3)ai向b(i+m)连容量无穷,费用f的边,ai向b(i+n)连容量无穷,费用f的边,ai向a(i+1)连容量无穷费用0的边

  然后zkw 50ms过了

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #define ll long long
 7 #define inf 0x3f3f3f3f
 8 #define N 2005
 9 using namespace std;
10 int day,n,m,p,s,f,S,T,tot,r[N],cur[N<<1],hd[N<<1],vis[N<<1],d[N<<1]; 
11 ll cost;
12 struct edge{int u,v,w,next,cap,flow;}e[N<<4];
13 void adde(int u,int v,int w,int c){
14     e[tot].u=u;
15     e[tot].v=v;
16     e[tot].w=w;
17     e[tot].cap=c;
18     e[tot].next=hd[u];
19     hd[u]=tot++;
20 }
21 
22 bool spfa(){
23     memset(d,0x3f,sizeof(d));
24     memset(vis,0,sizeof(vis));
25     deque<int>q;d[T]=0;q.push_back(T);
26     while(!q.empty()){
27         int u=q.front();q.pop_front();vis[u]=0;
28         for(int i=hd[u];~i;i=e[i].next){
29             if(e[i^1].cap<=e[i^1].flow)continue;
30             int w=e[i^1].w,v=e[i].v;
31             if(d[v]>d[u]+w){
32                 d[v]=d[u]+w;
33                 if(vis[v])continue;
34                 vis[v]=1;
35                 if(!q.empty()&&d[v]<d[q.front()])q.push_front(v);
36                 else q.push_back(v);
37             }
38         }
39     }
40     return d[S]<0x3f3f3f3f;
41 }
42 
43 int dfs(int u,int a){
44     if(!a||u==T)return a;
45     vis[u]=1;int f=0,fl=0;
46     for(int &i=cur[u];~i;i=e[i].next){
47         int v=e[i].v;
48         if(d[v]+e[i].w==d[u]&&!vis[v]&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
49             cost+=(ll)f*e[i].w;fl+=f;
50             e[i].flow+=f;
51             e[i^1].flow-=f;
52             a-=f;
53             if(!a)break;
54         }
55     }
56     vis[u]=0;return fl;
57 }
58 
59 int main(){
60 #ifdef wsy
61     freopen("data.in","r",stdin);
62 #else
63     //freopen(".in","r",stdin);
64     //freopen(".out","w",stdout);
65 #endif
66     memset(hd,-1,sizeof(hd));
67     scanf("%d",&day);S=0;T=(day<<1)+1;
68     for(int i=1;i<=day;i++)scanf("%d",&r[i]);
69     scanf("%d%d%d%d%d",&p,&m,&f,&n,&s);
70     for(register int i=1;i<=day;i++){
71         adde(S,i,0,r[i]);adde(i,S,0,0);
72         adde(S,i+day,p,inf);adde(i+day,S,-p,0);
73         if(i!=day)adde(i,i+1,0,inf),adde(i+1,i,0,0);
74         adde(i+day,T,0,r[i]);adde(T,i+day,0,0);
75         if(i+m<=day)adde(i,i+day+m,f,inf),adde(i+day+m,i,-f,0);
76         if(i+n<=day)adde(i,i+day+n,s,inf),adde(i+day+n,i,-s,0);
77     }
78     while(spfa()){
79         for(int i=S;i<=T;i++)cur[i]=hd[i];
80         dfs(S,inf);
81     }
82     printf("%lld",cost);
83     return 0;
84 }
View Code

  

  3.bzoj1433假期的宿舍

  我的方法跟网上其他博客有点不一样,随便YY的。把每个人拆成2个点ai bi,建立超级源汇S,T。

  (1)S向所有 外校人员的ai建立容量1的边

  (2)所有 在校的要回家的学生的bi向T连容量为1的边

  (3)对于一对相互认识的人bi->aj互相建容量无穷边

  (4)每个人的ai向bi建立容量1的边

  这样以后一个流就表示一个挪动方案

  

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #define inf 0x3f3f3f3f
 7 #define ll long long
 8 #define N 105 
 9 using namespace std;
10 int n,S,T,tot,cur[N],st[N],hd[N],gh[N],kn[N][N],d[N],vis[N];
11 struct edge{int v,next,cap,flow;}e[N*N*4];
12 void adde(int u,int v,int c){
13     e[tot].v=v;
14     e[tot].next=hd[u];
15     e[tot].cap=c;
16     e[tot].flow=0;
17     hd[u]=tot++;
18 }
19 
20 bool bfs(){
21     queue<int>q;
22     memset(vis,0,sizeof(vis));
23     q.push(S);d[S]=0;
24     while(!q.empty()){
25         int u=q.front();q.pop();vis[u]=1;
26         for(int i=hd[u];~i;i=e[i].next){
27             int v=e[i].v;
28             if(e[i].cap<=e[i].flow||vis[v])continue;
29             d[v]=d[u]+1;q.push(v);
30         }
31     }
32     return vis[T];
33 }
34 
35 int dfs(int u,int a){
36     if(u==T||!a)return a;
37     int fl=0,f;
38     for(int i=hd[u];~i;i=e[i].next){
39         int v=e[i].v;
40         if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
41             fl+=f;a-=f;
42             e[i].flow+=f;
43             e[i^1].flow-=f;
44             if(a<=0)break;
45         }
46     }
47     return fl;
48 }
49 int main(){
50 #ifdef wsy
51     freopen("data.in","r",stdin);
52 #else
53     //freopen(".in","r",stdin);
54     //freopen(".out","w",stdout);
55 #endif
56     int cas;scanf("%d",&cas);
57     while(cas--){
58         scanf("%d",&n);S=0;T=2*n+1;tot=0;
59         memset(hd,-1,sizeof(hd));
60         for(int i=1;i<=n;i++)scanf("%d",&st[i]);
61         
62     //    for(int i=1;i<=n;i++)if(!st[i])printf("%d ",i);puts("");
63         
64         for(int i=1;i<=n;i++)scanf("%d",&gh[i]);
65         
66     //    for(int i=1;i<=n;i++)if(st[i]&&gh[i])printf("%d ",i);puts("");
67         
68         for(int i=1;i<=n;i++)
69         for(int j=1;j<=n;j++)
70         scanf("%d",&kn[i][j]);
71         for(int i=1;i<=n;i++){
72             if(st[i]){
73                 if(gh[i])adde(i+n,T,1),adde(T,i+n,0);
74             }
75             else adde(S,i,1),adde(i,S,0);
76         }
77         for(int i=1;i<=n;i++)
78         for(int j=i+1;j<=n;j++){
79             if(!kn[i][j])continue;
80         //    printf("%d %d\n",i,j);
81             int f1=st[i],f2=st[j];
82             if(f1)adde(j+n,i,inf),adde(i,j+n,0);
83             if(f2)adde(i+n,j,inf),adde(j,i+n,0);
84         }
85         for(int i=1;i<=n;i++)
86         adde(i,i+n,1),adde(i+n,i,0);
87         while(bfs()){
88             for(int i=S;i<=T;i++)cur[i]=hd[i];
89             dfs(S,0x3f3f3f3f);
90         }
91         int fg=0;
92         for(int i=hd[S];~i;i=e[i].next)
93         if(e[i].cap-e[i].flow>0)fg=1;
94         if(fg)puts("T_T");
95         else puts("^_^");
96     }
97     return 0;
98 }
View Code

    

   4.bzoj1934Vote善意的投票

  最小割模型。

  S向1的人建容量1的边,0的人向T建容量1的边。认识的人互相建容量1的边。

  这样求出最小割后,与S相连的点集表示最终选1的人,与T相连表示选0,每条割边表示一个冲突。

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #define ll long long
 7 #define N 305
 8 using namespace std;
 9 int n,m,S,T,tot,hd[N],d[N],vis[N],cur[N];
10 struct edge{int v,next,cap,flow;}e[N*N*4];
11 void adde(int u,int v,int c){
12     e[tot].v=v;
13     e[tot].next=hd[u];
14     e[tot].cap=c;
15     e[tot].flow=0;
16     hd[u]=tot++;
17 }
18 
19 bool bfs(){
20     queue<int>q;
21     memset(vis,0,sizeof(vis));
22     q.push(S);d[S]=0;
23     while(!q.empty()){
24         int u=q.front();q.pop();vis[u]=1;
25         for(int i=hd[u];~i;i=e[i].next){
26             int v=e[i].v;
27             if(e[i].cap<=e[i].flow||vis[v])continue;
28             d[v]=d[u]+1;q.push(v);
29         }
30     }
31     return vis[T];
32 }
33 
34 int dfs(int u,int a){
35     if(u==T||!a)return a;
36     int fl=0,f;
37     for(int i=hd[u];~i;i=e[i].next){
38         int v=e[i].v;
39         if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
40             fl+=f;a-=f;
41             e[i].flow+=f;
42             e[i^1].flow-=f;
43             if(a<=0)break;
44         }
45     }
46     return fl;
47 }
48 int main(){
49     scanf("%d%d",&n,&m);
50     memset(hd,-1,sizeof(hd));
51     S=0;T=n+1;
52     for(int i=1;i<=n;i++){
53         int x;
54         scanf("%d",&x);
55         if(x)adde(S,i,1),adde(i,S,0);
56         else adde(i,T,1),adde(T,i,0);
57     }
58     for(int i=1;i<=m;i++){
59         int a,b;
60         scanf("%d%d",&a,&b);
61         adde(a,b,1);adde(b,a,1);
62     }
63     int flow=0;
64     while(bfs()){
65         for(int i=S;i<=T;i++)cur[i]=hd[i];
66         flow+=dfs(S,0x3f3f3f3f);
67     }
68     printf("%d",flow);
69     return 0;
70 }
View Code

 

  5.1854: [Scoi2010]游戏

      两种解法

 

  (1)二分图

  把每个物品和属性都当成点,物品为黑部,属性白部。物品向它有的属性建边。从属性1的点开始向下匹配,匹配到不成功即为答案。

  (2)并查集

  把属性当成点,物品当成边。那对于每一条边,可以选择他两端的一个点。

  如果一个联通块是一棵大小为n的树,我们可以从其中选出n-1个点。否则可以选出所有的点。

  记录联通块是不是树和联通块内最大的属性值,合并即可。

   选点肯定是先选出小的点来构成1,2,3,4,5……所以判断当一个属性是它所在联通块最大值时,此属性为答案

 

  6.bzoj1066蜥蜴

   很裸的最大流啊。拆点,每个格子拆成入点和出点,入点向出点连容量为高度的边。

  S向有蜥蜴的格子入点连容量1的边,可以跳出的边界的格子出点向T连容量无穷边。如果a格可以到达b格,a的出点连b的入点,容量无穷。

  1 #include
  2 #include
  3 #include
  4 #define inf 0x7fffffff
  5 using namespace std;
  6 struct data{int to,next,v;}e[500001];
  7 int r,c,d,cnt=1,ans,mp[21][21],mark[21][21],q[802],h[802],head[802];
  8 void ins(int u,int v,int w)
  9 {cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].v=w;}
 10 void insert(int u,int v,int w)
 11 {ins(u,v,w);ins(v,u,0);}
 12 bool judge(int x1,int y1,int x2,int y2)
 13 {
 14     if(((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))<=(d*d)&&mp[x1][y1]&&mp[x2][y2])return 1;
 15     return 0;
 16 }
 17 void build()
 18 {
 19      for(int x1=1;x1<=r;x1++)
 20         for(int y1=1;y1<=c;y1++)
 21            for(int x2=x1-d;x2<=x1+d;x2++)
 22               for(int y2=y1-d;y2<=y1+d;y2++)
 23      if(judge(x1,y1,x2,y2)&&(x1!=x2||y1!=y2))insert(mark[x1][y1]+400,mark[x2][y2],inf); 
 24      for(int i=1;i<=r;i++)
 25         for(int j=1;j<=c;j++)
 26            if(mp[i][j])insert(mark[i][j],mark[i][j]+400,mp[i][j]);
 27  } 
 28 bool bfs()
 29 {
 30      memset(h,-1,sizeof(h));
 31      int t=0,w=1,i,now;q[0]=h[0]=0;
 32      while(t<w)
 33      {
 34                now=q[t];t++;i=head[now];
 35                while(i)
 36                {
 37                        if(e[i].v&&h[e[i].to]==-1)
 38                        {
 39                            h[e[i].to]=h[now]+1;
 40                            q[w++]=e[i].to; 
 41                            }
 42                        i=e[i].next; 
 43                        }
 44                }
 45      if(h[801]==-1)return 0;return 1;
 46  }
 47 int dfs(int x,int f)
 48 {
 49     if(x==801)return f;
 50     int i=head[x],used=0,w;
 51     while(i)
 52     {
 53             if(e[i].v&&h[e[i].to]==h[x]+1)
 54             {
 55                 w=f-used;w=dfs(e[i].to,min(w,e[i].v));
 56                 e[i].v-=w;e[i^1].v+=w;
 57                 used+=w;if(used==f)return f;
 58                                           }
 59             i=e[i].next;
 60             }
 61     if(!used)h[x]=-1;
 62     return used;
 63 }
 64 void dinic(){while(bfs())ans-=dfs(0,inf);}
 65 int main()
 66 {
 67     scanf("%d%d%d",&r,&c,&d);
 68     char ch[21];
 69     for(int i=1;i<=r;i++)
 70     {
 71        scanf("%s",ch);
 72        for(int j=1;j<=c;j++)
 73            mp[i][j]=ch[j-1]-'0';
 74           }
 75     int tot=0;
 76     for(int i=1;i<=r;i++)
 77        for(int j=1;j<=c;j++)
 78        {tot++;mark[i][j]=tot;} 
 79     for(int i=1;i<=r;i++)
 80     {
 81        scanf("%s",ch);
 82        for(int j=1;j<=c;j++)
 83            if(ch[j-1]=='L')
 84              {insert(0,mark[i][j],1);ans++;}
 85           }
 86     for(int i=1;i<=d;i++)
 87        for(int j=d+1;j<=r-d;j++)
 88        {
 89           insert(mark[j][i]+400,801,inf);
 90           insert(mark[j][c-i+1]+400,801,inf);
 91           }
 92     for(int i=1;i<=d;i++)
 93        for(int j=1;j<=c;j++)
 94        {
 95           insert(mark[i][j]+400,801,inf);
 96           insert(mark[r-i+1][j]+400,801,inf);
 97           }
 98     build();
 99     dinic();
100     printf("%d",ans);
101     return 0;
102 }
View Code

 

 

    7.bzoj1070修车

  费用流。把车看作点,S向每辆车连容量1费用0的点。

  把每个工人拆成n个点,k点表示倒数第k个修这辆车。

  每个工人点向T连容量1费用0的边。

  每辆车向每个工人点连边,容量1,费用为k*cost,k即为这个工人倒数第k个修这辆车。

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #define ll long long
 7 #define N 105
 8 using namespace std;
 9 int n,m,tot,S,T,base,t[N][N],hd[N*N],vis[N*N],d[N*N],pre[N*N],a[N*N];
10 struct edge{int u,v,w,next,cap;}e[N*N*6];
11 bool spfa(int &flow,int &cost){
12     queue<int>q;
13     memset(pre,-1,sizeof(pre));
14     memset(d,0x3f,sizeof(d));
15     q.push(S);d[S]=0;a[S]=0x3f3f3f3f;
16     while(!q.empty()){
17         int u=q.front();q.pop();
18         vis[u]=0;
19         for(int i=hd[u];~i;i=e[i].next){
20             int v=e[i].v;
21             if(e[i].cap>0&&d[v]>d[u]+e[i].w){
22                 d[v]=d[u]+e[i].w;pre[v]=i;
23                 a[v]=min(a[u],e[i].cap);
24                 if(vis[v])continue;
25                 vis[v]=1;q.push(v);
26             }
27         }
28     }
29     if(d[T]==0x3f3f3f3f)return 0;
30     flow+=a[T];cost+=a[T]*d[T];
31     int u=T;
32     while(u!=S){
33         e[pre[u]].cap-=a[T];
34         e[pre[u]^1].cap+=a[T];
35         u=e[pre[u]].u;
36     }
37     return 1;
38 }
39 void adde(int u,int v,int w,int cap){
40     e[tot].u=u;e[tot].next=hd[u];e[tot].v=v;
41     e[tot].w=w;e[tot].cap=cap;hd[u]=tot++;
42 }
43 int get(int i,int j){return (j-1)*m+i;}
44 void build(int i,int j,int k){
45     adde(i+base,get(j,k),k*t[j][i],1);
46     adde(get(j,k),i+base,-k*t[j][i],0);
47 //    printf("%d %d %d\n",i+base,get(j,k),k*t[j][i]);
48 } 
49 int main(){
50     scanf("%d%d",&m,&n);
51     memset(hd,-1,sizeof(hd));
52     base=n*m;S=0;T=base+n+1;
53     for(int i=1;i<=n;i++)
54     for(int j=1;j<=m;j++)scanf("%d",&t[j][i]);    
55     for(int i=1;i<=n;i++)adde(S,i+base,0,1),adde(i+base,S,0,0)/*printf("%d %d 0\n",S,i+base)*/;
56     for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
57     for(int k=1;k<=n;k++)build(i,j,k);
58     for(int i=1;i<=base;i++)adde(i,T,0,1),adde(T,i,0,0)/*printf("%d %d 0\n",i,T)*/;
59     int flow=0,cost=0;
60     while(spfa(flow,cost));
61     printf("%.2lf",(double)cost/n);
62     return 0;
63 }
View Code

 

 

  8.bzoj1412狼和羊的故事

  很裸的最小割模型了。把狼和羊分开即可。

  S向狼连容量无穷边,羊向T连容量无穷边。

  狼向周围空地和羊连容量1的边,空地向周围空地和羊连容量1边。

  最小割后,和S连的点即表示狼的领地,与T相连的点表示羊的领地。

 

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #define ll long long
 7 #define inf 0x3f3f3f3f
 8 #define N 105
 9 using namespace std;
10 int n,m,S,T,tot,mp[N][N],hd[N*N],cur[N*N],d[N*N],vis[N*N];
11 int dx[]={0,0,1,-1};int dy[]={1,-1,0,0};
12 struct edge{int v,cap,next;}e[N*N*8];
13 int get(int i,int j){return (i-1)*m+j;}
14 bool check(int i,int j){return i>=1&&i<=n&&j>=1&&j<=m;}
15 void adde(int u,int v,int c){
16     e[tot].v=v;
17     e[tot].next=hd[u];
18     e[tot].cap=c;
19     hd[u]=tot++;
20 }
21 bool bfs(){
22     queue<int>q;
23     memset(vis,0,sizeof(vis));
24     d[S]=0;q.push(S);vis[S]=1;
25     while(!q.empty()){
26         int u=q.front();q.pop();
27         for(int i=hd[u];~i;i=e[i].next){
28             int v=e[i].v;
29             if(e[i].cap<=0||vis[v])continue;
30             d[v]=d[u]+1;vis[v]=1;q.push(v);
31         }
32     }
33     return vis[T];
34 }
35 int dfs(int u,int a){
36     if(u==T||!a)return a;
37     int fl=0,f;
38     for(int &i=cur[u];~i;i=e[i].next){
39         if(e[i].cap<=0)continue;
40         int v=e[i].v;
41         if(d[v]==d[u]+1&&(f=dfs(v,min(a,e[i].cap)))){
42             fl+=f;a-=f;e[i].cap-=f;
43             e[i^1].cap+=f;if(!a)break;
44         }
45     }
46     return fl;
47 }
48 int main(){
49 #ifdef wsy
50     freopen("data.in","r",stdin);
51 #else
52     //freopen(".in","r",stdin);
53     //freopen(".out","w",stdout);
54 #endif
55     scanf("%d%d",&n,&m);
56     memset(hd,-1,sizeof(hd));
57     S=0;T=n*m+1;
58     for(int i=1;i<=n;i++)
59     for(int j=1;j<=m;j++){
60         scanf("%d",&mp[i][j]);
61         if(mp[i][j]==1)adde(S,get(i,j),inf),adde(get(i,j),S,0);
62         else if(mp[i][j]==2)adde(get(i,j),T,inf),adde(T,get(i,j),0);
63     }
64     for(int i=1;i<=n;i++)
65     for(int j=1;j<=m;j++){
66         if(mp[i][j]==2)continue;
67         int idx=get(i,j);
68         for(int k=0;k<4;k++){
69             int nx=i+dx[k],ny=j+dy[k];
70             if(!check(nx,ny))continue;
71             int nid=get(nx,ny);
72             if(mp[i][j]==1){
73                 if(mp[nx][ny]!=1)adde(idx,nid,1),adde(nid,idx,0);
74             }
75             else if(mp[nx][ny]!=1)adde(idx,nid,1),adde(nid,idx,0);
76         }
77     }
78     int ans=0;
79     while(bfs()){
80         for(int i=S;i<=T;i++)cur[i]=hd[i];
81         ans+=dfs(S,0x3f3f3f3f);
82     }
83     printf("%d",ans);
84     return 0;
85 }
View Code

 

 

 

  

  

  

   每道题都因为一些zz错误调了很久,还真TM是愉悦的一天。

 

  

 

转载于:https://www.cnblogs.com/wsy01/p/7918482.html

你可能感兴趣的:(停课集训 11.28)