吃了某种抑制神经的药的蒟蒻真是药丸......
别问我为什么推到今天才补,才不告诉你我拖延症犯了......
T1:
一看就是不可做的构造题......
前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 }