zoukankan      html  css  js  c++  java
  • Codeforces 985G. Team Players

    Description

    (n) 个人 , (m) 对人有冲突 , 你要从这 (n) 个人中选出三个人成为一组 , 使得同一组的人不存在一对有冲突
    题面

    Solution

    容斥
    答案=总方案-至少有一个与 (i) 相连的+至少有 (2) 个与 (i) 相连的-(i,j,k) 都互相连接的方案数
    前面三种都比较好求,讨论一下 (i,j,k) 的偏序关系就行了
    关于第三种情况,需要 (O(m^2)) 枚举 , 只需要枚举度数较小的两个,最大的那个直接判断是否与前面两个相连就好了
    这样做最坏复杂度是 (O(n*sqrt{n})) 的 ,(CF)(Tutorial) 有证明.

    #include<bits/stdc++.h>
    using namespace std;
    template<class T>void gi(T &x){
    	int f;char c;
    	for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
    	for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
    }
    typedef unsigned long long ll;
    const int N=2e5+10;
    int n,m,head[N],nxt[N*4],to[N*4],num=0,Head[N],b[N],a[N];
    ll s[N],ss[N],A,B,C,ans=0,in[N];
    inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
    inline void Link(int x,int y){nxt[++num]=Head[x];to[num]=y;Head[x]=num;}
    int main(){
      freopen("pp.in","r",stdin);
      freopen("pp.out","w",stdout);
      int x,y;
      cin>>n>>m>>A>>B>>C;
      for(int i=1;i<=m;i++)gi(x),gi(y),link(x,y),link(y,x),in[x]++,in[y]++;
      for(int i=0,u;i<n;i++)
    	  for(int j=head[i];j;j=nxt[j])
    		  if(in[u=to[j]]>in[i]|| (in[u]==in[i] && u>i))Link(i,u);
      //+0						  
      for(int i=0;i<n;i++){
    	  s[i]=s[i-1]+i*A;
    	  ss[i]=ss[i-1]+s[i-1]+B*i*i;
    	  ans+=ss[i-1]+1ll*i*(i-1)/2*C*i;
      }
      for(int i=0;i<n;i++){
    	  m=0;
    	  for(int j=head[i];j;j=nxt[j])b[a[++m]=to[j]]=i+1;
    	  sort(a+1,a+m+1);s[m+1]=0;
    	  //-1
    	  for(int j=1;j<=m && a[j]<i;j++){
    		  ans-=(a[j]*A+i*B)*(n-i-1)+1ll*(i+n)*(n-i-1)/2*C;
    		  ans-=(a[j]*A+i*C)*(i-a[j]-1)+1ll*(a[j]+i)*(i-a[j]-1)/2*B;
    		  ans-=(a[j]*B+i*C)*a[j]+1ll*a[j]*(a[j]-1)/2*A;
    	  }
    	  //+2
    	  for(int j=1;j<=m && a[j]<i;j++){
    		  s[j]=s[j-1]+a[j];
    		  ans+=s[j-1]*A+(j-1)*(a[j]*B+C*i);
    	  }
    	  for(int j=m;j>=1 && a[j]>i;j--){
    		  s[j]=s[j+1]+a[j];
    		  ans+=s[j+1]*C+(m-j)*(a[j]*B+A*i);
    	  }
    	  for(int j=1;j<m;j++)
    		  if(a[j]<i && a[j+1]>i)ans+=s[j]*A*(m-j)+i*B*j*(m-j)+s[j+1]*C*j;
    	  //-3
    	  for(int j=Head[i];j;j=nxt[j])
    		  for(int k=Head[to[j]];k;k=nxt[k]){
    			  if(b[to[k]]!=i+1)continue;
    			  int c[3]={i,to[j],to[k]};
    			  sort(c,c+3);
    			  ans-=A*c[0]+B*c[1]+C*c[2];
    		  }  
      }
      cout<<ans<<endl;
      return 0;
    }
    
    
  • 相关阅读:
    COM 组件创建实例失败,原因是出现以下错误: c001f011 (Microsoft.SqlServer.ManagedDTS)
    df: `/root/.gvfs': Permission denied
    ora-03113 end-of-file on communication channel 故障处理
    ESXi克隆虚拟机时网卡需要重新设置的问题
    Spark重点难点知识总结
    Hive,Hive on Spark和SparkSQL区别
    Spark分区数、task数目、core数目、worker节点数目、executor数目梳理
    spark RDD中的partition和hdfs中的block的关系
    Spark容错机制
    【干货】大数据框架整理
  • 原文地址:https://www.cnblogs.com/Yuzao/p/9185148.html
Copyright © 2011-2022 走看看