zoukankan      html  css  js  c++  java
  • 2021牛客暑期多校训练营3

    2021牛客暑期多校训练营3

    B Black and white

    对于一个位置((i,j)),选择这个位置的数就给((out_i,in_j))连一条边,考虑四个点((i,j)(i,k)(l,j)(l,k))被涂成黑色对应了(out_i out_l)(in_i in_l)构成的一个四元环。其中一个点自动涂黑就是四元环断一条边,即这四个点刚好连通。
    类似的,全部位置涂黑其实就是求图中的一棵生成树。
    所以用prim(O(n^2))求最小生成树即可。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define LL long long 
    #define INF 2147483647
    #define N 5050 
    int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    	return sum*f;
    }
    int e[N*2][N*2];
    int dis[N*2];
    bool vis[N*2];
    signed main(){
    	int n=read(),m=read();
    	LL a=read(),b=read(),c=read(),d=read(),p=read();
    	for(int i=1;i<=n+m;i++)
    		for(int j=1;j<=m+n;j++)
    			e[i][j]=INF;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++){
    			a=(a*a%p*b%p+a*c%p+d)%p;
    			e[i][j+n]=e[j+n][i]=a;
    		}
    	for(int i=1;i<=n+m;i++)dis[i]=INF;
    	dis[1]=0;
    	LL ans=0;
    	for(int i=1;i<=n+m;i++){
    		int u,tmp=INF;
    		for(int j=1;j<=n+m;j++)
    			if(vis[j]==0&&dis[j]<tmp)tmp=dis[j],u=j;
    		ans+=dis[u];vis[u]=1;
    		for(int j=1;j<=n+m;j++)
    			dis[j]=min(dis[j],e[u][j]);
    	}
    	printf("%lld",ans); 
    	return 0;
    } 
    

    C Minimum grid

    考虑最大的(C_j)(B_i)
    填数时只能选择满足条件的行和列并的若干个格子。
    一个格子((i,j))中可以填数代表选择了从(out_i)(in_j)的一条边。
    其实就是二分图的最小边覆盖。
    最小边覆盖=总点数-最大匹配
    求最大匹配即可。
    之后求次大的(C_j)(B_i)直到满足所有条件为止。
    那么证明若干个最小边覆盖(就是最优的选点方案)没有冲突呢?
    发现可以使答案变优的解在满足条件的行和列的交上。
    这些交不能在考虑其他(C_j)(B_i)时填数,不能使答案更优就随便填,我们不关心具体位置。因为题目保证了至少有一种可行方案,所以不用考虑。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=2111;
    int cnt,head[N*2],match[N*2],id_n[N],id_m[N];
    bool vis[N*2],E[N][N];
    struct edge{
    	int to,nxt;
    }e[N*N];
    struct limit{
    	int id,type,w;
    }c[N*2];
    bool cmp(limit a,limit b){
    	return a.w>b.w;
    }
    void add_edge(int u,int v){
    	cnt++;
    	e[cnt].nxt=head[u];
    	e[cnt].to=v;
    	head[u]=cnt;
    }
    int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    	return sum*f;
    }
    bool dfs(int u){
    	for(int i=head[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(vis[v])continue;
    		vis[v]=1;
    		if(!match[v]||dfs(match[v])){
    			match[v]=u;
    			return true;
    		}
    	}
    	return false;
    }
    int main(){
    	int n=read(),m=read(),k=read();
    	for(int i=1;i<=n;i++)
    		c[i].type=1,c[i].w=read(),c[i].id=i;	 
    	for(int i=1;i<=n;i++)
    		c[i+n].type=2,c[i+n].w=read(),c[i+n].id=i;
    	for(int i=1;i<=m;i++)E[read()][read()]=1;
    	sort(c+1,c+1+2*n,cmp);
    	int now=1;
    	int ans=0;
    	int num_n=0,num_m=0;
    	while(now<=n*2+1){
    		if(c[now].w!=c[now-1].w){
    			cnt=0;
    			memset(head,0,sizeof(head));
    			for(int i=1;i<=num_n;i++)
    				for(int j=1;j<=num_m;j++){
    					if(E[id_n[i]][id_m[j]]==0)continue;
    					add_edge(id_n[i],id_m[j]+n);
    					add_edge(id_m[j]+n,id_n[i]); 
    				}
    			memset(match,0,sizeof(match));
    			int tmp=0;
    			for(int i=1;i<=num_n;i++){
    				memset(vis,0,sizeof(vis));
    				tmp+=dfs(id_n[i]);
    			}
    			ans+=(num_n+num_m-tmp)*c[now-1].w;
    			num_n=num_m=0;
    		}
    		if(c[now].type==1)id_n[++num_n]=c[now].id;
    		if(c[now].type==2)id_m[++num_m]=c[now].id;
    		now++;
    	}
    	printf("%d",ans);
    	return 0;
    }
    

    F 24dian

    爆搜,心态爆炸,做题之前一定要确定题目的意思。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<map>
    using namespace std;
    int pos[10],book[10],n,m,cnt,b[40000][10],c[10],type[10],id[10],vis[10],d[10];
    bool Map[15][15][15][15];
    double a[10];
    int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){
    		if(ch=='-')f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9'){
    		sum=sum*10+ch-'0';
    		ch=getchar();
    	}
    	return sum*f;
    }
    bool cnm(){
    	double ans;
    	for(int i=1;i<=n;i++)a[i]=c[id[i]];
    	for(int i=1;i<n;i++)pos[i]=d[i];
    	bool flag=0;
    	for(int i=1;i<=n-1;i++){
    		if(type[i]==1)ans=a[pos[i]]+a[pos[i]+1];
    		if(type[i]==2)ans=a[pos[i]]-a[pos[i]+1];
    		if(type[i]==3)ans=a[pos[i]]*a[pos[i]+1];
    		if(type[i]==4){
    			if(a[pos[i]+1]==0)return false;
    			if(flag==0){
    				int x=(int)a[pos[i]],y=(int)a[pos[i]+1]; 
    				if(x%y!=0)flag=1;
    			}
    			ans=a[pos[i]]/a[pos[i]+1];
    		}
    		a[pos[i]]=ans;
    		for(int j=pos[i]+1;j<=n;j++)a[j]=a[j+1];
    		for(int j=i+1;j<=n-1;j++)
    			if(pos[j]>pos[i])pos[j]--;
    	}
    	if(abs(ans-1.0*m)<=1e-5&&flag==0)Map[c[1]][c[2]][c[3]][c[4]]=1;
    	if(abs(ans-1.0*m)<=1e-5)return true;
    	else return false;
    }
    bool mmp(int x){
    	if(x==n+1){
    		if(cnm())return true;
    		else return false;
    	}
    	int flag=0; 
    	for(int i=1;i<=n;i++){
    		if(vis[i])continue;
    		id[x]=i;
    		vis[i]=1;
    		if(mmp(x+1))flag=1;
    		vis[i]=0; 
    	}
    	if(flag==1)return true;
    	return false;
    }
    bool check(int x){
    	if(x==n){
    		vis[1]=vis[2]=vis[3]=vis[4]=0;
    		if(mmp(1))return true;
    		else return false;
    	}
    	int flag=0;
    	for(int i=1;i<=4;i++){
    		type[x]=i;
    		if(check(x+1))flag=1;
    	}
    	if(flag)return true;
    	return false;
    }
    bool judge(int x){//x是 
    	if(x==n){
    		if(check(1))return true;
    		return false;
    	}
    	int flag=0;
    	for(int i=1;i<=n-1;i++){
    		if(book[i])continue;
    		book[i]=1;
    		d[x]=i;//第x个操作 i 是第几个位置的符号 
    		if(judge(x+1))flag=1;
    		book[i]=0;
    	}
    	if(flag)return true;
    	return false;
    }
    void dfs(int x){
    	if(x==n+1){
    		book[1]=book[2]=book[3]=0; 
    		if(judge(1)){
    			if(Map[c[1]][c[2]][c[3]][c[4]]==1)return;
    			cnt++;
    			for(int i=1;i<=n;i++)b[cnt][i]=c[i];
    		}
    		return;
    	}
    	for(int i=1;i<=13;i++){
    		if(i<c[x-1])continue;
    		c[x]=i;
    		dfs(x+1);
    	}
    }
    int main(){
    	n=read(),m=read();
    	dfs(1);
    	cout<<cnt<<endl;
    	for(int i=1;i<=cnt;i++){
    		for(int j=1;j<=n;j++){
    			cout<<b[i][j]<<" ";
    		}
    		cout<<endl;
    	}
    	return 0;
    } 
    
  • 相关阅读:
    udacity android 实践笔记: lesson 4 part b
    iosiPhone屏幕尺寸、分辨率及适配
    【基础练习】【区间DP】codevs2102 石子归并2(环形)题解
    Spring Boot MyBatis 连接数据库
    知乎日报 API 分析
    Dijkstra算法
    win7远程桌面连接不上,解决办法
    ECharts图表中级入门之formatter:夜谈关于ECharts图表内的数据格式化方法
    myeclipse 连接svn服务器验证位置时发生错误 404 forbidden
    极路由系列 刷机方法
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/15038056.html
Copyright © 2011-2022 走看看