标签:
描述:给定一张图(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 }
BZOJ 4086: [Sdoi2015]travel(SDOI2015 round2 day1)(分类讨论+容斥原理)
标签:
原文地址:http://www.cnblogs.com/New-Godess/p/4570361.html