吃了某种抑制神经的药的蒟蒻真是药丸......
别问我为什么推到今天才补,才不告诉你我拖延症犯了......

T1:

北京集训:20180316
一看就是不可做的构造题......
前20分爆搜,后20分估计是什么状压,然而并不会写......
考虑f[i][j][k][l]表示礼物i在j,k在l是否可行,
我们可以通过一个类似于点分治的dfs预处理出这些信息。
如果我们把每个礼物在某个节点看做新图上一个点的话,我们就要在新图上找一个大小为n的团......
最大团什么的,不是NP问题吗?这玩意人干事?
算了,写个爆搜搞搞就好......
成绩出来发现跑过了4个点,第一个点WA了woc......
正解是2-sat。
考虑f[i][j][0/1]表示礼物i是否在点j的的子树中。
那么对于礼物x,y经过点pos,我们需要:
f[son][x]&f[son][y] = 0
f[pos][x]|f[pos][y] = 1
f[son][x]&f[son2][x] = 0
f[pos][x] -> f[fa][x]。
然后2-sat建图按照tarjan求出强连通的顺序输出方案即可。
然而写挂了还是30分......
考场30分暴力:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<bitset>
 7 using namespace std;
 8 const int maxn=252;
 9 
10 int s[maxn],t[maxn<<1],nxt[maxn<<1];
11 bitset<maxn> can[maxn][maxn][maxn],now[maxn][maxn];
12 bitset<maxn> sons[maxn],full;
13 vector<pair<int,int> > vs[maxn];
14 bool bad[maxn][maxn];
15 int fm[maxn],ans[maxn];
16 int n,m,q;
17 
18 inline void addedge(int from,int to) {
19     static int cnt = 0;
20     t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
21 }
22 inline void dfs(int pos,int fa,int bel) {
23     sons[bel][pos] = 1 , fm[pos] = bel;
24     for(int at=s[pos];at;at=nxt[at]) if( t[at] != fa ) dfs(t[at],pos,bel);
25 }
26 inline void solvepos(int pos) {
27     if( !vs[pos].size() ) return;
28     for(int at=s[pos];at;at=nxt[at]) {
29         sons[t[at]] &= 0;
30         dfs(t[at],pos,t[at]);
31     }
32     for(unsigned j=0;j<vs[pos].size();j++) {
33         const int x = vs[pos][j].first , y = vs[pos][j].second;
34         for(int i=1;i<=n;i++) if( i != pos ) {
35             can[x][i][y] &= ( full ^ sons[fm[i]] );
36             can[y][i][x] &= ( full ^ sons[fm[i]] );
37         }
38     }
39 }
40 inline void cpy(int dst,int sou) {
41     for(int i=1;i<=m;i++) now[dst][i] = now[sou][i];
42 }
43 inline void afs(int pos) {
44     if( pos == 1 ) {
45         for(int i=1;i<=m;i++)
46             for(int j=1;j<=m;j++)
47                 now[i][j] = full;
48     }
49     if( pos > m ) {
50         for(int i=1;i<=m;i++) printf("%d%c",ans[i],i!=m?' ':'\n');
51         exit(0);
52     }
53     for(int i=1,fail;i<=n;i++) if( now[pos][pos][i] && !bad[pos][i] ) {
54         ans[pos] = i , fail = 0;
55         cpy(pos+1,pos);
56         for(int j=1;j<=m;j++) {
57             now[pos+1][j] &= can[pos][i][j];
58             if( !now[pos+1][j].count() ) {
59                 fail = 1;
60                 break;
61             }
62         }
63         if( !fail ) afs(pos+1);
64     }
65 }
66 inline void getbad() {
67     for(int i=1;i<=m;i++)
68         for(int j=1;j<=n;j++)
69             for(int k=1;k<=m;k++)
70                 if( !can[i][j][k].count() ) {
71                     bad[i][j] = 1;
72                     break;
73                 }
74 }
75 int main() {
76     scanf("%d%d%d",&n,&m,&q);
77     for(int i=1,a,b;i<n;i++) {
78         scanf("%d%d",&a,&b);
79         addedge(a,b) , addedge(b,a);
80     }
81     for(int i=1,a,b,t;i<=q;i++) {
82         scanf("%d%d%d",&a,&b,&t);
83         vs[t].push_back(make_pair(a,b));
84     }
85     for(int i=1;i<=n;i++) full[i] = i;
86     for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) for(int k=1;k<=m;k++) can[i][j][k] = full;
87     for(int i=1;i<=n;i++) solvepos(i);
88     getbad();
89     afs(1);
90     return 0;
91 }
View Code

相关文章:

  • 2021-09-29
  • 2022-01-17
  • 2021-06-13
  • 2022-01-27
  • 2022-01-14
  • 2021-09-13
  • 2021-09-18
  • 2021-08-11
猜你喜欢
  • 2021-04-20
  • 2021-08-14
  • 2022-01-20
  • 2021-09-16
  • 2021-11-27
  • 2021-05-02
  • 2021-12-09
相关资源
相似解决方案