怕不是我再不写题解这题就该成没人做也没人会的千古谜题了......

T1:

Cmd2001的毒瘤水题题解
仔细分析题面,发现相同就是广义SAM上节点相同,相似就是广义SAM上为从根到某个点路径的前缀。、
直接SAM上跑从根开始,每个点下界为1的最小流即可。
代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<map>
  6 #include<queue>
  7 #define debug cout
  8 using namespace std;
  9 const int maxn=5e3+1e2;
 10 const int inf=0x3f3f3f3f;
 11   
 12 int in[maxn],n,ans,sum;
 13   
 14 namespace NetworkFlow {
 15     int s[maxn<<2],t[maxn<<6],nxt[maxn<<6],f[maxn<<6],dep[maxn<<2],deg[maxn<<2],cnt=1;
 16     int bak[maxn<<2],bcnt;
 17     int st,ed,_s,_t;
 18     inline void coredge(int from,int to,int flow) {
 19         t[++cnt] = to , f[cnt] = flow ,
 20         nxt[cnt] = s[from] , s[from] = cnt;
 21     }
 22     inline void singledge(int from,int to,int flow) {
 23         coredge(from,to,flow) , coredge(to,from,0);
 24     }
 25     inline bool bfs() {
 26         memset(dep,-1,sizeof(dep)) , dep[st] = 0;
 27         queue<int> q; q.push(st);
 28         while( q.size() ) {
 29             const int pos = q.front(); q.pop();
 30             for(int at=s[pos];at;at=nxt[at])
 31                 if( f[at] && !~dep[t[at]] ) {
 32                     dep[t[at]] = dep[pos] + 1 , q.push(t[at]);
 33                 }
 34         }
 35         return ~dep[ed];
 36     }
 37     inline int dfs(int pos,int flow) {
 38         if( pos == ed ) return flow;
 39         int ret = 0 , now = 0;
 40         for(int at=s[pos];at;at=nxt[at])
 41             if( f[at] && dep[t[at]] > dep[pos] ) {
 42                 now = dfs(t[at],min(flow,f[at])) ,
 43                 ret += now , flow -= now ,
 44                 f[at] -= now , f[at^1] += now;
 45                 if( !flow ) return ret;
 46             }
 47         if( !ret ) dep[pos] = -1;
 48         return ret;
 49     }
 50     inline int dinic() {
 51         int ret = 0 , now = 0;
 52         while( bfs() ) {
 53             while( ( now = dfs(st,inf) ) )
 54                 ret += now;
 55         }
 56         return ret;
 57     }
 58     inline int findflow() {
 59         for(int at=s[_t];at;at=nxt[at])
 60             if( t[at] == _s ) return f[at^1];
 61     }
 62     inline void backup() {
 63         memcpy(bak,s,sizeof(s)) , bcnt = cnt;
 64     }
 65     inline void restore() {
 66         memcpy(s,bak,sizeof(bak)) , cnt = bcnt;
 67     }
 68 }
 69   
 70 namespace SAM {
 71     map<int,int> ch[maxn<<1];
 72     int fa[maxn<<1],len[maxn<<1],root,last,cnt;
 73       
 74     inline int NewNode(int ll) {
 75         len[++cnt] = ll;
 76         return cnt;
 77     }
 78     inline void extend(int x) {
 79         int p = last;
 80         int np = NewNode(len[p]+1);
 81         while( p && ch[p].find(x) == ch[p].end() ) ch[p][x] = np , p = fa[p];
 82         if( !p ) fa[np] = root;
 83         else {
 84             int q = ch[p][x];
 85             if( len[q] == len[p] + 1 ) fa[np] = q;
 86             else {
 87                 int nq = NewNode(len[p]+1);
 88                 ch[nq] = ch[q] , fa[nq] = fa[q];
 89                 fa[np] = fa[q] = nq;
 90                 while( p && ch[p][x] == q ) ch[p][x] = nq , p = fa[p];
 91             }
 92         }
 93         last = np;
 94     }
 95     inline void Ex_extend(int* sou,int li) {
 96         last = root;
 97         for(int i=1;i<=li;i++) {
 98             if( ch[last].find(sou[i]) != ch[last].end() ) last = ch[last][sou[i]];
 99             else extend(sou[i]);
100         }
101     }
102 }
103   
104 inline void build() {
105     using SAM::ch;using SAM::cnt;
106     using namespace NetworkFlow;
107     _s = cnt * 2 + 1 , _t = _s + 1 , st = _t + 1 , ed = st + 1;
108     #define cov(x) (x+cnt)
109     for(int i=1;i<=cnt;i++) {
110         if( i != 1 ) ++deg[i] , --deg[cov(i)];
111         for(map<int,int>::iterator it=ch[i].begin();it!=ch[i].end();it++) {
112             const int tar = it->second;
113             if( i == 1 ) singledge(_s,tar,1);
114             else singledge(cov(i),tar,1);
115         }
116         if( i != 1 ) singledge(cov(i),_t,1);
117     }
118     backup();
119     for(int i=1;i<=_t;i++) {
120         if( !deg[i] ) continue;
121         if( deg[i] > 0 ) singledge(i,ed,deg[i]) , sum += deg[i];
122         else singledge(st,i,-deg[i]);
123     }
124     singledge(_t,_s,inf);
125 }
126 inline int getans() {
127     using namespace NetworkFlow;
128     int d = dinic();
129     if( d != sum ) return -1; // No solution .
130     int ret = findflow();
131     restore();
132     st = _t , ed = _s;
133     int dd = dinic();
134     return ret - dd;
135 }
136  
137 int main() {
138     static int m;
139     SAM::root = SAM::NewNode(0);
140     scanf("%d",&m);
141     while(m--) {
142         scanf("%d",&n);
143         for(int i=1;i<=n;i++) scanf("%d",in+i);
144         SAM::Ex_extend(in,n);
145     }
146     build();
147     ans = getans();
148     printf("%d\n",ans);
149     return 0;
150 }
View Code

相关文章:

  • 2021-10-22
  • 2021-12-20
  • 2021-06-03
  • 2021-12-22
  • 2022-12-23
  • 2022-12-23
  • 2021-05-01
  • 2021-11-26
猜你喜欢
  • 2021-06-26
  • 2022-12-23
  • 2021-07-21
  • 2021-06-03
  • 2022-02-13
  • 2021-07-05
  • 2021-09-06
相关资源
相似解决方案