zoukankan      html  css  js  c++  java
  • Loj#3026-「ROIR 2018 Day1」管道监控【Trie,费用流】

    正题

    题目链接:https://loj.ac/p/3026


    题目大意

    给出(n)个点的一棵外向树,然后(m)个字符串和费用表示你每次可以花费这个费用覆盖路径字符串和给出字符串相等的路径,求覆盖所有边的最小花费(可以重复覆盖)

    输出方案

    (1leq nleq 500,1leq mleq10^5,sum |S|leq 10^6)


    解题思路

    注意到(n)很小,可以考虑枚举计算所有路径的最小花费,先构一个(Trie)即可处理这部分。

    然后考虑怎么覆盖的问题,和[NOI2008] 志愿者招募类似的,我们可以通过边调走流来实现覆盖问题。

    先原点向每一个叶子连流量为1的边,设(siz_x)表示(x)的子树中有多少个叶子那么(x)(fa_x)连接流量为(siz_x-1)的边,然后根向汇点连流量为(siz_1)的边。

    这样就保证了每条边都至少有一个流量被调走,但是需要考虑单链上的重复覆盖所以还需要每个点向儿子连无向流量的边。


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define ll long long
    using namespace std;
    const ll N=510,M=1e6+10;
    struct node{
    	ll to,next,w;
    }a[N];
    ll n,m,t,tot,ans,MF,ls[N],siz[N],fa[N];
    ll cnt,ch[M][26],cost[M],fail[M],mark[M];
    queue<int> q;char s[M];
    void addl(ll x,ll y,ll w){
    	a[++tot].to=y;
    	a[tot].next=ls[x];
    	ls[x]=tot;a[tot].w=w;
    	return;
    }
    void Insert(char *s,ll val,ll num){
    	ll x=1,m=strlen(s);
    	for(ll i=0;i<m;i++){
    		ll c=s[i]-'a';
    		if(!ch[x][c])ch[x][c]=++cnt;
    		x=ch[x][c];
    	}
    	if(cost[x]>val)cost[x]=val,mark[x]=num;
    	return;
    }
    void GetFail(){
    	for(ll i=0;i<26;i++)q.push(ch[1][i]);
    	while(!q.empty()){
    		ll x=q.front();
    		for(ll i=0;i<26;i++){
    			if(!ch[x][i])ch[x][i]=ch[fail[x]][i];
    			else{
    				fail[ch[x][i]]=ch[fail[x]][i];
    				q.push(ch[x][i]);
    			}
    		}
    	}
    	return;
    }
    namespace NF{
    	struct node{
    		ll to,next,w,c,typ;
    	}a[N*N];
    	ll tot=1,s,t,ls[N],f[N],mf[N],pre[N];
    	bool v[N];
    	void addl(ll x,ll y,ll w,ll c,ll mk){
    		a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;a[tot].c=c;//a[tot].typ=mk;
    		a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;a[tot].c=-c;a[tot].typ=mk;
    		return;
    	}
    	bool SPFA(){
    		memset(f,0x3f,sizeof(f));
    		q.push(s);v[s]=1;f[s]=0;
    		mf[s]=f[0];mf[t]=0;
    		while(!q.empty()){
    			ll x=q.front();v[x]=0;q.pop();
    			for(ll i=ls[x];i;i=a[i].next){
    				ll y=a[i].to;
    				if(a[i].w&&f[x]+a[i].c<f[y]){
    					f[y]=f[x]+a[i].c;
    					pre[y]=i;mf[y]=min(mf[x],a[i].w);
    					if(!v[y])v[y]=1,q.push(y);
    				}
    			}
    		}
    		return mf[t];
    	}
    	void Updata(){
    		ll x=t;ans+=mf[t]*f[t];MF+=mf[t];
    		while(x!=s){
    			a[pre[x]].w-=mf[t];
    			a[pre[x]^1].w+=mf[t];
    			x=a[pre[x]^1].to;
    		}
    		return;
    	}
    	void GetAns(){
    		while(SPFA())
    		Updata();
    		return;
    	}
    	void Print(){
    		ll sum=0;
    		for(ll i=2;i<=tot;i++)
    			if(a[i].typ)sum+=a[i].w;
    		printf("%lld
    ",sum);
    		for(ll i=2;i<=tot;i++)
    			if(a[i].typ){
    				while(a[i].w)
    					printf("%lld %lld %lld
    ",a[i^1].to,a[i].to,a[i].typ),a[i].w--;
    			}
    	}
    }
    void calc(ll x,ll p,ll s){
    	if(!p)return;
    	if(cost[p]<=1e9)
    		NF::addl(x,s,n,cost[p],mark[p]);
    	for(ll i=ls[x];i;i=a[i].next)
    		calc(a[i].to,ch[p][a[i].w],s);
    	return;
    }
    void solve(ll x){
    	siz[x]+=(!ls[x]);
    	if(!ls[x])NF::addl(NF::s,x,1,0,0);
    	calc(x,1,x);
    	for(ll i=ls[x];i;i=a[i].next){
    		NF::addl(x,a[i].to,n,0,0);
    		solve(a[i].to),siz[x]+=siz[a[i].to];
    	}
    	if(fa[x]&&siz[x]>1)
    		NF::addl(x,fa[x],siz[x]-1,0,0);
    	return;
    }
    signed main()
    {
    	memset(cost,0x3f,sizeof(cost));
    	scanf("%lld%lld%lld",&n,&m,&t);
    	for(ll i=2;i<=n;i++){
    		ll x;char op[3];
    		scanf("%lld%s",&fa[i],op);
    		addl(fa[i],i,op[0]-'a');
    	}
    	cnt=1;
    	for(ll i=1;i<=m;i++){
    		ll c;
    		scanf("%lld%s",&c,s);
    		Insert(s,c,i);
    	}
    	NF::s=n+1;NF::t=n+2;
    	solve(1);
    	NF::addl(1,NF::t,siz[1],0,0);
    	NF::GetAns();
    	if(MF!=siz[1])return puts("-1")&0;
    	printf("%lld
    ",ans);
    	if(t)NF::Print();
    	return 0;
    }
    
  • 相关阅读:
    [puppet]如何设置全局exec path
    noVNC配置小结
    [CloudOps]解决Windows系列镜像在Openstack上蓝屏
    解决 /usr/bin/env: php: No such file or directory
    构建一个多区域的公有云平台:Stacklab
    ssh自动添加hostkey到know_hosts
    A few thoughts about Open Source Software
    简单翻译:Understanding Linux Network Internals 2.2. net_device Structure
    近期小结
    [Music]《our love will always last》
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15024142.html
Copyright © 2011-2022 走看看