码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 4086: [Sdoi2015]travel(SDOI2015 round2 day1)(分类讨论+容斥原理)

时间:2015-06-12 00:24:45      阅读:1259      评论:0      收藏:0      [点我收藏+]

标签:

描述:给定一张图(n<1000,m<5000)求有多少点对u,v有不重复经过其他点,共经过k个点的路径。(k<=7)

这个做法应该不是正解吧。。顺便说下SDOI的几道题在BZ上都要卡常数真是哭瞎了QAQ

然后我们知道k这么小,考虑下每个k怎么乱搞吧。。。

k=2:直接枚举每条边就行啦

k=3:枚举中间点,然后再考虑两端端点O(m^2)

k=4:枚举两边的点,然后枚举边考虑中间的两个点是否联通O(m^2)

k=5:枚举夹在中间的两个点,然后记录所有可能的中间点数目tot,然后枚举外面的两点,若tot-两点是否为中间点>0那么就可行

k=6:思路大概相同,记链为x->u->p->q->v->y 枚举u,v记下所有可能的二元组p,q,记总数为tot,出现x的次数为Cx,然后在枚举x,y若tot-Cx-Cy+x,y是否为二元组>0,那么就可行

k=7:依旧是考虑容斥,记链为x->u->p->z->q->v->y,先记下对所有p,q中z的集合,然后枚举u,v,对中间的所有可行的三元组,记录总数为tot,x在两端出现次数为Cx,在中间次数为Mx

x在中,y在两端的次数为ESx,y;x,y都在两端的次数为Sx,y,再枚举x,y,若tot-Cx-Cy-Mx-My+MSx,y+MSy,x+Sx,y>0,那么可行

对于k<7的情况可以O(m^2)完成,K=7的情况有点难估计(O(M^2*N)大概吧)不过能过就对了

好啦好像很短但还是写了5KB左右,主要思路还是分情况讨论然后枚举端点上容斥啦

CODE:

技术分享
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 using namespace std;
  7 #define maxn 1010
  8 #define maxm 5010
  9 bool bo[maxn][maxn],b[maxn][maxn];
 10 vector<int> e[maxn];
 11 #define pb push_back
 12 int n;
 13 inline void task2(){
 14     for (int i=1;i<=n;i++) 
 15         for (int j=0;j<e[i].size();j++) bo[i][e[i][j]]=1;
 16 }
 17 inline void task3(){
 18     for (int i=1;i<=n;i++) 
 19         for (int j=0;j<e[i].size();j++) 
 20             for (int k=j+1;k<e[i].size();k++) 
 21                 bo[e[i][j]][e[i][k]]=bo[e[i][k]][e[i][j]]=1;
 22 }
 23 inline void task4(){
 24     for (int i=1;i<=n;i++) 
 25         for (int j=i+1;j<=n;j++) 
 26             for (int k=0;k<e[i].size();k++) 
 27                 for (int l=0;l<e[j].size();l++)    {
 28                     int u=e[i][k],v=e[j][l];
 29                     if (u!=v&&u!=j&&v!=i&&b[u][v]) bo[i][j]=bo[j][i]=1;
 30                 }
 31 }
 32 inline void task5(){
 33     static int cnt[maxn][maxn];
 34     memset(cnt,0,sizeof(cnt));
 35     for (int i=1;i<=n;i++) 
 36         for (int j=0;j<e[i].size();j++) 
 37             for (int k=j+1;k<e[i].size();k++) 
 38                 cnt[e[i][j]][e[i][k]]++,cnt[e[i][k]][e[i][j]]++;
 39     for (int i=1;i<=n;i++) 
 40         for (int j=i+1;j<=n;j++) 
 41             for (int k=0;k<e[i].size();k++) 
 42                 for (int l=0;l<e[j].size();l++){ 
 43                     if (i==j||e[i][k]==e[j][l]||e[i][k]==j||e[j][l]==i||cnt[i][j]-b[i][e[j][l]]-b[j][e[i][k]]<=0) continue;
 44                     bo[e[i][k]][e[j][l]]=bo[e[j][l]][e[i][k]]=1;
 45                 }
 46 }
 47 inline void task6(){
 48     static int cnt[maxn],ti[maxn];
 49     static int is[maxn][maxn];
 50     static int L;
 51     for (int i=1;i<=n;i++) 
 52         for (int j=i+1;j<=n;j++){
 53             L++;
 54             int tot=0;
 55             for (int k=0;k<e[i].size();k++) 
 56                 for (int l=0;l<e[j].size();l++)     
 57                     if (e[i][k]!=e[j][l]&&e[i][k]!=j&&e[j][l]!=i&&b[e[i][k]][e[j][l]]) {
 58                         if (ti[e[i][k]]!=L) ti[e[i][k]]=L,cnt[e[i][k]]=0;
 59                         if (ti[e[j][l]]!=L) ti[e[j][l]]=L,cnt[e[j][l]]=0;
 60                         cnt[e[i][k]]++,cnt[e[j][l]]++,tot++,is[e[i][k]][e[j][l]]=L;
 61                     }
 62             for (int k=0;k<e[i].size();k++) 
 63                 for (int l=0;l<e[j].size();l++) {
 64                     if (e[i][k]==e[j][l]||e[i][k]==j||e[j][l]==i||
 65                         tot-(ti[e[i][k]]==L?cnt[e[i][k]]:0)-(ti[e[j][l]]==L?cnt[e[j][l]]:0)+(is[e[i][k]][e[j][l]]==L)+(is[e[j][l]][e[i][k]]==L)<=0) continue;
 66                     bo[e[i][k]][e[j][l]]=bo[e[j][l]][e[i][k]]=1;
 67                 }
 68         }
 69 }
 70 int L;
 71 vector<int> id[maxn][maxn];
 72 int is_cnt[maxn],cnt[maxn],ex[maxn][maxn],is_ex[maxn][maxn],mid[maxn],is_mid[maxn],side[maxn][maxn],is_side[maxn][maxn];
 73 inline void addcnt(int x) {
 74     if (is_cnt[x]!=L) is_cnt[x]=L,cnt[x]=0;
 75     cnt[x]++;
 76 }inline void addmid(int x) {
 77     if (is_mid[x]!=L) is_mid[x]=L,mid[x]=0;
 78     mid[x]++;
 79 }inline void addex(int x,int y) {
 80     if (is_ex[x][y]!=L) is_ex[x][y]=L,ex[x][y]=0;
 81     ex[x][y]++;
 82 }inline void addside(int x,int y) {
 83     if (is_side[x][y]!=L) is_side[x][y]=L,side[x][y]=0;
 84     side[x][y]++;
 85 }
 86 inline int quecnt(int x) {return is_cnt[x]==L?cnt[x]:0;}
 87 inline int quemid(int x) {return is_mid[x]==L?mid[x]:0;}
 88 inline int queex(int x,int y) {return is_ex[x][y]==L?ex[x][y]:0;}
 89 inline int queside(int x,int y) {return is_side[x][y]==L?side[x][y]:0;}
 90 inline void task7(){
 91     for (int i=1;i<=n;i++) 
 92         for (int j=1;j<=n;j++) id[i][j].clear();
 93     for (int i=1;i<=n;i++) 
 94         for (int j=0;j<e[i].size();j++) 
 95             for (int k=j+1;k<e[i].size();k++){ 
 96                 id[e[i][j]][e[i][k]].pb(i);
 97                 id[e[i][k]][e[i][j]].pb(i);
 98             }
 99     for (int i=1;i<=n;i++) 
100         for (int j=i+1;j<=n;j++){
101             L++;
102             int tot=0;
103             for (int k=0;k<e[i].size();k++) 
104                 for (int l=0;l<e[j].size();l++)    {
105                     int u=e[i][k],v=e[j][l];
106                     if (u==v||u==j||v==i) continue;
107                     for (int r=0;r<id[u][v].size();r++) {
108                         int mid=id[u][v][r];
109                         if (mid==i||mid==j) continue;
110                         tot++,addcnt(u),addcnt(v);
111                         addex(id[u][v][r],u);
112                         addex(id[u][v][r],v);
113                         addmid(id[u][v][r]);
114                         addside(u,v);
115                     }
116                 }
117             for (int k=0;k<e[i].size();k++) 
118                 for (int l=0;l<e[j].size();l++)    {
119                     int u=e[i][k],v=e[j][l];
120                     if (u==v||u==j||v==i||tot-quecnt(u)-quecnt(v)-quemid(u)-quemid(v)+queex(u,v)+queex(v,u)+queside(u,v)<=0) continue;
121                     bo[u][v]=bo[v][u]=1;
122                 }
123         }
124 }
125 int main(){
126     int T,m,k;
127     scanf("%d",&T);
128     while (T--) {
129         scanf("%d%d%d",&n,&m,&k);
130         for (int i=1;i<=n;i++) e[i].clear();
131         memset(b,0,sizeof(b));
132         memset(bo,0,sizeof(bo));
133         for (int i=1;i<=m;i++) {
134             int u,v;
135             scanf("%d%d",&u,&v);
136             if (u==v) continue;
137             if (b[u][v]) continue;
138             e[u].pb(v);e[v].pb(u);
139             b[u][v]=b[v][u]=1;
140         }
141         if (k==2) task2();
142         if (k==3) task3();
143         if (k==4) task4();
144         if (k==5) task5();
145         if (k==6) task6();
146         if (k==7) task7();
147         for (int i=1;i<=n;i++,puts("")) 
148             for (int j=1;j<=n;j++) putchar(bo[i][j]?Y:N);
149     }
150     return 0;
151 }
View Code

BZOJ 4086: [Sdoi2015]travel(SDOI2015 round2 day1)(分类讨论+容斥原理)

标签:

原文地址:http://www.cnblogs.com/New-Godess/p/4570361.html

(0)
(1)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!