• #dp#nssl 1478 题



    分析

    (f[i])表示第(i)个是否幸存,(dp[i][j])表示若第(i)个幸存,第(j)个是否必死
    倒序枚举人,如果存在(dp[i][a[x]],dp[i][b[x]])同时为是,为了避免矛盾,第(i)个必死
    如果存在(dp[i][a[x]],dp[i][b[x]])其中一个为是,那么另一个也为是
    最后枚举两个点(i,j)若没有一个点(k)使得(dp[i][k],dp[j][k])同时为是,那么((i,j))幸存


    代码

    #include <cstdio>
    #include <cctype>
    #define rr register
    using namespace std;
    const int N=411,M=50011;
    int n,m,a[M],b[M],ans; bool f[N],dp[N][N];
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    signed main(){
    	n=iut(),m=iut();
    	for (rr int i=1;i<=m;++i) a[i]=iut(),b[i]=iut();
    	for (rr int i=1;i<=n;++i){
    		f[i]=dp[i][i]=1;
    		for (rr int j=m;j>=1;--j){
    			if (!dp[i][a[j]]&&!dp[i][b[j]]) continue;
    			if (dp[i][a[j]]&&dp[i][b[j]]){f[i]=0; break;}
    			dp[i][a[j]]=dp[i][b[j]]=1;
    		}
    	}
    	for (rr int i=1;i<n;++i)
    	for (rr int j=i+1;j<=n;++j)
    	if (f[i]&&f[j]){
    		rr int flag=1;
    		for (rr int k=1;k<=n;++k)
    		if (dp[i][k]&&dp[j][k]){
    			flag=0; break;
    		}
    		if (flag) ++ans;
    	}
    	return !printf("%d",ans); 
    }
    
  • 相关阅读:
    Linux基础命令---sudo
    Linux基础命令---yes
    Linux基础命令---shutdown
    Divide Two Integers
    java 判断两个数是否异号
    字节顺序的详细解释(转)
    java无符号移位(>>>)和有符号移位(>>)
    java 参数化类型
    c++事件内核对象(event)进程间激活(转)
    windows多线程编程(一)(转)
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13504615.html
Copyright © 2020-2023  润新知