zoukankan      html  css  js  c++  java
  • 6.29 省选模拟赛 坏题 AC自动机 dp 图论

    avatar
    avatar

    考场上随手构造了一组数据把自己卡掉了 然后一直都是掉线状态了。

    最后发现这个东西不是subtask -1的情况不多 所以就没管无解直接莽 写题有点晚 故没调出来。。

    考虑怎么做 容易想到建立AC自动机 然后不能跑到结尾节点 fail是结尾节点的也不能跑。

    把那些节点抽出来就可以随便跑了 题目描述非常丧心病狂 两个字符串相等描述的莫名其妙。

    不过这道题的本意让我们求出两端在环内的字符串个数。

    发现如果存在不是简单环的话是无解的 如果出现两个环的路径上还是环的话也同时无解。

    对于前者 一个非常妙的trick是 看这个强联通分量的边数 边数等于点数还是边数大于点数。这个trick 非常的稀有!想了很久都没想到。

    对于后者 DAG上的dp也可以顺带求出 对于答案也可以很容易的在DAG上dp求出。

    后者这个情况很容易被忽略掉 这里要注意!

    code
    //#include<bits/stdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<ctime>
    #include<cstdlib>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    #include<string>
    #include<utility>
    #include<queue>
    #include<vector>
    #include<algorithm>
    #include<deque>
    #include<stack>
    #include<list>
    #include<bitset>
    #include<set>
    #include<map>
    #define INF 1000000000000000000ll
    #define rep(p,n,i) for(int i=p;i<=n;++i)
    #define fep(n,p,i) for(int i=n;i>=p;--i)
    #define vep(p,n,i) for(int i=p;i<n;++i)
    #define db double
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define put(x) printf("%d
    ",x)
    #define pb push_back
    #define ll long long
    #define db double
    #define putl(x) printf("%lld
    ",x)
    #define mod 1000000007
    #define en(i) t[i].en
    #define fail(i) t[i].fail
    using namespace std;
    char *fs,*ft,buf[1<<15];
    inline char getc()
    {
    	return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
    	int x=0,f=1;char ch=getc();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
    	return x*f;
    }
    const int MAXN=10010,maxn=2000000;
    int n,T,id,cnt,cc,top,len,len1;
    char a[MAXN];
    int q[MAXN],v[MAXN],f[MAXN],ru[MAXN],num[MAXN];
    int dfn[MAXN],c[MAXN],s[MAXN],low[MAXN],g[MAXN],ff[MAXN];
    int lin[MAXN],ver[maxn],nex[maxn],lin1[MAXN],ver1[maxn],nex1[maxn];
    inline void add(int x,int y){ver[++len]=y;nex[len]=lin[x];lin[x]=len;}
    inline void add1(int x,int y){ver1[++len1]=y;nex1[len1]=lin1[x];lin1[x]=len1;}
    struct wy{int ch[26];int en,fail;}t[MAXN];
    inline void insert(int n)
    {
    	int now=0;
    	rep(1,n,i)
    	{
    		int w=a[i]-'a';
    		if(!t[now].ch[w])t[now].ch[w]=++id;
    		now=t[now].ch[w];
    	}
    	en(now)=1;
    }
    inline void build()
    {
    	int l=0,r=0;
    	rep(0,T,i)if(t[0].ch[i])q[++r]=t[0].ch[i];
    	while(++l<=r)
    	{
    		int x=q[l];
    		rep(0,T,i)
    		{
    			int tn=t[x].ch[i];
    			if(!tn)t[x].ch[i]=t[fail(x)].ch[i];
    			else fail(tn)=t[fail(x)].ch[i],q[++r]=tn;
    		}
    	}
    	rep(1,r,i)en(q[i])|=en(fail(q[i]));
    }
    inline void dfs(int x)
    {
    	dfn[x]=++cnt;low[x]=cnt;s[++top]=x;
    	for(int i=lin[x];i;i=nex[i])
    	{
    		int tn=ver[i];
    		if(!dfn[tn])
    		{
    			dfs(tn);
    			low[x]=min(low[x],low[tn]);
    		}
    		else if(!c[tn])low[x]=min(low[x],dfn[tn]);
    	}
    	if(dfn[x]==low[x])
    	{
    		++cc;int y=-1;
    		while(y!=x)
    		{
    			y=s[top--];
    			c[y]=cc;
    			++g[cc];
    		}
    	}
    }
    inline void topsort()
    {
    	int l=0,r=0;
    	rep(1,cc,i)if(!ru[i])q[++r]=i;
    	int ans=0;
    	while(++l<=r)
    	{
    		int x=q[l];
    		f[x]+=v[x];if(v[x])ans+=f[x],++ff[x];
    		if(ff[x]>2){puts("-1");return;}
    		for(int i=lin1[x];i;i=nex1[i])
    		{
    			int tn=ver1[i];
    			--ru[tn];ff[tn]=max(ff[tn],ff[x]);
    			f[tn]+=f[x];
    			if(!ru[tn])q[++r]=tn;
    		}
    	}
    	put(ans);
    }
    int main()
    {
    	freopen("huai.in","r",stdin);
    	freopen("huai.out","w",stdout);
    	gt(T);gt(n);--T;
    	rep(1,n,i)
    	{
    		scanf("%s",a+1);
    		int len=strlen(a+1),flag=0;
    		rep(1,len,j)if(a[j]-'a'>T){flag=1;}
    		if(flag)continue;
    		insert(len);
    	}
    	build();
    	rep(0,id,i)
    	{
    		if(en(i))continue;
    		rep(0,T,j)
    		{
    			int tn=t[i].ch[j];
    			if(en(tn))continue;
    			add(i,tn);
    			//cout<<i<<' '<<tn<<endl;
    		}
    	}
    	dfs(0);
    	rep(0,id,i)
    	{
    		if(en(i))continue;
    		for(int j=lin[i];j;j=nex[j])
    		{
    			int tn=ver[j];
    			if(c[tn]==c[i]){++num[c[tn]];continue;}
    			add1(c[tn],c[i]);
    		}
    	}
    	rep(1,cc,i)
    	{
    		if(num[i]>g[i]){puts("-1");return 0;}
    		if(num[i]==g[i])v[i]=1;
    	}
    	topsort();//可以反向dfs或者正向topsort.
    	return 0;
    }
    
  • 相关阅读:
    【HDOJ】4982 Goffi and Squary Partition
    【HDOJ】4983 Goffi and GCD
    【算法导论】学习笔记——第7章 快速排序
    【算法导论】学习笔记——第6章 堆排序
    【HDOJ】4956 Poor Hanamichi
    【HDOJ】2492 Ping pong
    【Linux】鸟哥的Linux私房菜基础学习篇整理(十二)
    【Linux】鸟哥的Linux私房菜基础学习篇整理(十一)
    统计硬币
    放大的X
  • 原文地址:https://www.cnblogs.com/chdy/p/13205954.html
Copyright © 2011-2022 走看看