• 【题解】洛谷 P6651 「SWTR-05」Chain | 20211011 模拟赛 食物链(foodchain)【拓扑排序 容斥】


    题目链接

    题目链接

    题意

    对于 DAG,定义一条食物链为其极长路径。多次询问,删除 (k) 个点,剩余多少原有的食物链。(nleq 2 imes 10^3,sum kleq 2 imes 10^6)

    题解

    添加超级源汇点以方便处理。预处理 (i)(j) 的路径数,(2^k) 容斥显然,按照拓扑序排序后 DP 则 (O(k))

    #include<bits/stdc++.h>
    using namespace std;
    const int BUF_SIZ=20*1024*1024;
    char buf[BUF_SIZ],*cur=buf;
    int getint(){
    	int ans=0;
    	char c=*cur++;
    	while(c<'0'||c>'9')c=*cur++;
    	while(c>='0'&&c<='9'){
    		ans=ans*10+c-'0';
    		c=*cur++;
    	}
    	return ans;
    }
    void putint(int x){
    	if(x==0){
    		putchar('0');
    		return;
    	}
    	if(x/10)putint(x/10);
    	putchar(x%10+'0');
    }
    const int N=2e3+10,mod=1e9+7;
    int _(int x){ return x>=mod?x-mod:x; }
    vector<int>to[N];
    int deg[N],ged[N];
    int p[N],rk[N];
    int f[N][N];
    int g[20];
    
    int main(){
    //	ios::sync_with_stdio(0);
    //	cin.tie(0);cout.tie(0);
    	freopen("foodchain.in","r",stdin);
    	freopen("foodchain.out","w",stdout);
    	fread(buf,BUF_SIZ,1,stdin);
    	int n=getint(),m=getint();
    	for(int i=0;i<m;i++){
    		int x=getint(),y=getint();
    		to[x].push_back(y);
    		++deg[y];
    		++ged[x];
    	}
    	for(int i=1;i<=n;i++){
    		if(deg[i]==0){
    			to[0].push_back(i);
    			++deg[i];
    			++ged[0];
    		}
    		if(ged[i]==0){
    			to[i].push_back(n+1);
    			++deg[n+1];
    			++ged[i];
    		}
    	}
    	queue<int>q;
    	q.push(0);
    	int tmp=0;
    	while(q.size()){
    		int t=q.front();q.pop();
    		rk[t]=tmp;
    		p[tmp++]=t;
    		for(int i:to[t]){
    			--deg[i];
    			if(!deg[i])q.push(i);
    		}
    	}
    	for(int i=0;i<=n+1;i++){
    		int *g=f[i];
    		g[i]=1;
    		for(int j=0;j<=n+1;j++){
    			for(int k:to[p[j]])
    				g[k]=_(g[k]+g[p[j]]);
    		}
    	}
    	
    	int Q=getint();
    	while(Q--){
    		int k=getint();
    		vector<int>v;
    		v.push_back(0);
    		for(int i=0;i<k;i++)v.push_back(getint());
    		v.push_back(n+1);
    		sort(v.begin(),v.end(),[&](int x,int y){ return rk[x]<rk[y]; });
    		g[0]=mod-1;
    		for(int i=1;i<=k+1;i++){
    			g[i]=0;
    			for(int j=0;j<i;j++)
    				g[i]=(g[i]+g[j]*1ll*(mod-f[v[j]][v[i]]))%mod;
    		}
    		putint(g[k+1]);
    		putchar('
    ');
    	}
    	return 0;
    }
    
    
    
    知识共享许可协议
    若文章内无特别说明,公开文章采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
  • 相关阅读:
    csharp:Validate email address using C#
    Sql:SQL Server CREATE SEQUENCE statement
    机器学习实战---SVD简化数据
    机器学习实战---PCA降维
    机器学习实战---使用FP-growth算法来高效发现频繁项集
    机器学习实战---使用Apriori算法进行关联分析
    机器学习实战---集成学习AdaBoost算法
    支持向量机核函数的实现
    支持向量机SMO算法实现(注释详细)
    帧缓冲
  • 原文地址:https://www.cnblogs.com/wallbreaker5th/p/15394640.html
Copyright © 2020-2023  润新知